SissiFeng commited on
Commit
71f7aba
·
1 Parent(s): 9502e34
Files changed (1) hide show
  1. app.py +103 -163
app.py CHANGED
@@ -22,24 +22,27 @@ logging.basicConfig(
22
  )
23
  logger = logging.getLogger("bambu-analysis")
24
 
25
- # Environment Variables - 尝试从环境变量获取,如果没有则使用默认值
26
- HOST = os.environ.get("host", "mqtt.bambulab.com")
27
- PORT = int(os.environ.get("port", "8883"))
28
- USERNAME = os.environ.get("username", "bblp")
29
- PASSWORD = os.environ.get("password", "bblp")
30
  DEFAULT_SERIAL = "0309CA471800852"
31
 
32
- # Global variables
33
- client = None
34
  latest_data = {
35
  "bed_temperature": "N/A",
36
  "nozzle_temperature": "N/A",
37
  "status": "N/A",
38
- "update_time": "Waiting for data..."
39
  }
40
 
 
 
 
 
41
  def create_client(host, port, username, password):
42
- """创建并配置MQTT客户端"""
43
  global client
44
  try:
45
  logger.info(f"Creating MQTT client for {host}:{port}")
@@ -48,7 +51,6 @@ def create_client(host, port, username, password):
48
  client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS)
49
  client.on_connect = on_connect
50
  client.on_message = on_message
51
- client.on_disconnect = on_disconnect
52
 
53
  logger.info("Connecting to MQTT broker...")
54
  client.connect(host, port)
@@ -59,95 +61,68 @@ def create_client(host, port, username, password):
59
  return False
60
 
61
  def on_connect(client, userdata, flags, rc):
62
- """MQTT连接回调"""
63
- if rc == 0:
64
- logger.info("Successfully connected to MQTT broker")
65
- serial = DEFAULT_SERIAL
66
- response_topic = f"bambu_a1_mini/response/{serial}"
67
- request_topic = f"bambu_a1_mini/request/{serial}"
68
-
69
- try:
70
- client.subscribe(response_topic)
71
- logger.info(f"Subscribed to {response_topic}")
72
-
73
- # 发送初始请求
74
- client.publish(request_topic, json.dumps("HI"))
75
- logger.info(f"Sent initial request to {request_topic}")
76
-
77
- # 更新状态
78
- global latest_data
79
- latest_data["status"] = "Connected"
80
- latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
81
- except Exception as e:
82
- logger.error(f"Error in on_connect callback: {e}")
83
- else:
84
- logger.error(f"Failed to connect to MQTT broker with code: {rc}")
85
 
86
  def on_message(client, userdata, message):
87
- """MQTT消息回调"""
 
 
88
  try:
89
- logger.info(f"Received message on topic: {message.topic}")
90
  data = json.loads(message.payload)
91
  logger.debug(f"Message content: {data}")
92
 
93
- global latest_data
94
  latest_data["bed_temperature"] = data.get("bed_temperature", "N/A")
95
  latest_data["nozzle_temperature"] = data.get("nozzle_temperature", "N/A")
96
  latest_data["status"] = data.get("status", "N/A")
97
- latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
98
  except Exception as e:
99
  logger.error(f"Error parsing MQTT message: {e}")
100
 
101
- def on_disconnect(client, userdata, rc):
102
- """MQTT断开连接回调"""
103
- logger.warning(f"Disconnected from MQTT broker with code: {rc}")
104
 
105
- global latest_data
106
- latest_data["status"] = "Disconnected"
107
- latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
108
 
109
- if rc != 0:
110
- logger.warning("Unexpected disconnection. Attempting to reconnect...")
111
- try:
112
- create_client(HOST, PORT, USERNAME, PASSWORD)
113
- except Exception as e:
114
- logger.error(f"Failed to reconnect: {e}")
115
-
116
- def get_data(serial=DEFAULT_SERIAL):
117
- """获取打印机状态数据"""
118
- logger.info("Requesting printer data")
119
- try:
120
- global client
121
- if client is None or not client.is_connected():
122
- logger.warning("MQTT client not connected. Attempting to connect...")
123
- create_client(HOST, PORT, USERNAME, PASSWORD)
124
 
125
- request_topic = f"bambu_a1_mini/request/{serial}"
126
- response_topic = f"bambu_a1_mini/response/{serial}"
127
-
128
- logger.info(f"Subscribing to {response_topic}")
129
- if client and client.is_connected():
130
- client.subscribe(response_topic)
131
-
132
- # 发送请求
133
- logger.info(f"Sending data request to {request_topic}")
134
- client.publish(request_topic, json.dumps("HI"))
135
-
136
- return (
137
- latest_data["status"],
138
- latest_data["bed_temperature"],
139
- latest_data["nozzle_temperature"],
140
- latest_data["update_time"]
141
- )
142
- else:
143
- logger.error("MQTT client not available")
144
- return ("Disconnected", "N/A", "N/A", "MQTT not connected")
145
- except Exception as e:
146
- logger.error(f"Error in get_data: {e}")
147
- return (f"Error: {str(e)}", "N/A", "N/A", time.strftime("%Y-%m-%d %H:%M:%S"))
 
 
 
 
 
 
 
148
 
149
- def send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed, serial=DEFAULT_SERIAL):
150
  """发送打印参数到打印机"""
 
151
  logger.info(f"Sending parameters to {serial}: nozzle={nozzle_temp}, bed={bed_temp}, speed={print_speed}, fan={fan_speed}")
152
  try:
153
  params = {
@@ -159,7 +134,7 @@ def send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed, serial=
159
 
160
  request_topic = f"bambu_a1_mini/request/{serial}"
161
 
162
- if client and client.is_connected():
163
  client.publish(request_topic, json.dumps({
164
  'command': 'set_parameters',
165
  'parameters': params
@@ -212,73 +187,68 @@ def health_check():
212
  status = {
213
  "app": "running",
214
  "time": time.strftime("%Y-%m-%d %H:%M:%S"),
215
- "mqtt_connected": client is not None and client.is_connected() if client else False,
216
  "latest_update": latest_data["update_time"]
217
  }
218
  logger.info(f"Health check: {status}")
219
  return status
220
 
221
  # API端点函数
222
- def api_get_status(serial=DEFAULT_SERIAL):
223
  """API端点:获取状态"""
224
- logger.info(f"API call: get_status for {serial}")
225
  try:
226
- return get_data(serial)
227
  except Exception as e:
228
- logger.error(f"Error in api_get_status: {e}")
229
  return ("Error", "N/A", "N/A", str(e))
230
 
231
- def api_get_image():
232
  """API端点:获取图像"""
233
- logger.info("API call: get_image")
234
  try:
235
  img = capture_image()
236
- return get_image_base64(img)
237
  except Exception as e:
238
- logger.error(f"Error in api_get_image: {e}")
239
  return None
240
 
241
- def api_send_parameters(params):
242
- """API端点:发送参数"""
243
- logger.info(f"API call: send_parameters with {params}")
244
  try:
245
- serial = params.get('serial', DEFAULT_SERIAL)
246
- return send_print_parameters(
247
- params.get('nozzle_temp', 200),
248
- params.get('bed_temp', 60),
249
- params.get('print_speed', 60),
250
- params.get('fan_speed', 100),
251
- serial
 
 
 
 
 
 
252
  )
253
  except Exception as e:
254
- logger.error(f"Error in api_send_parameters: {e}")
255
- return f"Error: {str(e)}"
256
 
257
- def api_health_check():
258
- """API端点:健康检查"""
259
- logger.info("API call: health_check")
260
  try:
261
- return health_check()
262
  except Exception as e:
263
- logger.error(f"Error in api_health_check: {e}")
264
- return {"status": "error", "error": str(e)}
265
-
266
- # 初始化MQTT客户端
267
- try:
268
- logger.info("Initializing MQTT client")
269
- mqtt_connected = create_client(HOST, PORT, USERNAME, PASSWORD)
270
- if not mqtt_connected:
271
- logger.warning("Starting without MQTT connection")
272
- except Exception as e:
273
- logger.error(f"Failed to initialize MQTT: {e}")
274
- logger.warning("Starting without MQTT connection")
275
 
276
  # 创建主界面
277
  with gr.Blocks(title="Bambu A1 Mini Print Control") as demo:
278
  gr.Markdown("# Bambu A1 Mini Print Control")
279
 
280
  with gr.Row():
281
- serial = gr.Textbox(DEFAULT_SERIAL, label="Serial Number")
282
  refresh_btn = gr.Button("Refresh Status")
283
 
284
  with gr.Row():
@@ -304,7 +274,6 @@ with gr.Blocks(title="Bambu A1 Mini Print Control") as demo:
304
  # 连接按钮
305
  refresh_btn.click(
306
  fn=get_data,
307
- inputs=[serial],
308
  outputs=[current_status, current_bed_temp, current_nozzle_temp, last_update]
309
  )
310
 
@@ -315,44 +284,10 @@ with gr.Blocks(title="Bambu A1 Mini Print Control") as demo:
315
 
316
  send_params_btn.click(
317
  fn=send_print_parameters,
318
- inputs=[nozzle_temp, bed_temp, print_speed, fan_speed, serial],
319
  outputs=[current_status]
320
  )
321
 
322
- # 创建API端点
323
- with gr.Blocks() as api_blocks:
324
- gr.Interface(
325
- fn=api_get_status,
326
- inputs=gr.Textbox(value=DEFAULT_SERIAL, label="Serial Number"),
327
- outputs="json",
328
- title="Get Printer Status",
329
- description="Get the current status of the printer"
330
- )
331
-
332
- gr.Interface(
333
- fn=api_get_image,
334
- inputs=None,
335
- outputs="json",
336
- title="Get Print Image",
337
- description="Get the current print image as base64"
338
- )
339
-
340
- gr.Interface(
341
- fn=api_send_parameters,
342
- inputs="json",
343
- outputs="text",
344
- title="Send Print Parameters",
345
- description="Send parameters to the printer"
346
- )
347
-
348
- gr.Interface(
349
- fn=api_health_check,
350
- inputs=None,
351
- outputs="json",
352
- title="Health Check",
353
- description="Check the health of the application"
354
- )
355
-
356
  # 自动刷新线程
357
  def auto_refresh():
358
  """自动刷新状态的后台线程"""
@@ -361,7 +296,7 @@ def auto_refresh():
361
  try:
362
  time.sleep(5)
363
  logger.debug("Auto-refreshing printer status")
364
- status, bed_temp, nozzle_temp, update_time = get_data(DEFAULT_SERIAL)
365
 
366
  # 更新UI
367
  current_status.update(value=status)
@@ -377,9 +312,14 @@ threading.Thread(target=auto_refresh, daemon=True).start()
377
  # 启动应用
378
  if __name__ == "__main__":
379
  logger.info("Starting Bambu A1 Mini Print Control application")
380
- # 启动主界面
381
- demo.queue().launch(show_error=True)
382
 
383
- # 启动API端点
384
- # 注意:在实际部署中,这些API端点应该与主界面集成在一起
385
- # 这里分开只是为了演示目的
 
 
 
 
 
 
 
 
22
  )
23
  logger = logging.getLogger("bambu-analysis")
24
 
25
+ # Environment Variables - 使用同事的配置方式
26
+ HOST = "mqtt.bambulab.com"
27
+ PORT = 8883
28
+ USERNAME = "bblp"
29
+ PASSWORD = "bblp"
30
  DEFAULT_SERIAL = "0309CA471800852"
31
 
32
+ # Global variables to store received data - 完全保持同事的数据结构
 
33
  latest_data = {
34
  "bed_temperature": "N/A",
35
  "nozzle_temperature": "N/A",
36
  "status": "N/A",
37
+ "update_time": "Waiting for data...",
38
  }
39
 
40
+ # MQTT Client setup - 完全保持同事的客户端设置
41
+ client = None
42
+ response_topic = None # Will be set dynamically
43
+
44
  def create_client(host, port, username, password):
45
+ """创建并配置MQTT客户端 - 使用同事的代码"""
46
  global client
47
  try:
48
  logger.info(f"Creating MQTT client for {host}:{port}")
 
51
  client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS)
52
  client.on_connect = on_connect
53
  client.on_message = on_message
 
54
 
55
  logger.info("Connecting to MQTT broker...")
56
  client.connect(host, port)
 
61
  return False
62
 
63
  def on_connect(client, userdata, flags, rc):
64
+ """MQTT连接回调 - 使用同事的代码"""
65
+ logger.info(f"Connected with result code {rc}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  def on_message(client, userdata, message):
68
+ """MQTT消息回调 - 使用同事的代码"""
69
+ global latest_data
70
+ logger.info("Received message")
71
  try:
 
72
  data = json.loads(message.payload)
73
  logger.debug(f"Message content: {data}")
74
 
 
75
  latest_data["bed_temperature"] = data.get("bed_temperature", "N/A")
76
  latest_data["nozzle_temperature"] = data.get("nozzle_temperature", "N/A")
77
  latest_data["status"] = data.get("status", "N/A")
78
+ latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
79
  except Exception as e:
80
  logger.error(f"Error parsing MQTT message: {e}")
81
 
82
+ def get_data(serial=DEFAULT_SERIAL):
83
+ """获取打印机状态数据 - 使用同事的代码"""
84
+ global client, response_topic, latest_data
85
 
86
+ logger.info(f"Requesting data for printer {serial}")
 
 
87
 
88
+ if client is None:
89
+ logger.info("Creating new MQTT client")
90
+ create_client(HOST, PORT, USERNAME, PASSWORD)
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ request_topic = f"bambu_a1_mini/request/{serial}"
93
+ response_topic = f"bambu_a1_mini/response/{serial}"
94
+
95
+ logger.info(f"Subscribing to {response_topic}")
96
+ client.subscribe(response_topic)
97
+
98
+ # 发送请求获取数据
99
+ logger.info(f"Publishing request to {request_topic}")
100
+ client.publish(request_topic, json.dumps("HI"))
101
+
102
+ # 等待数据更新
103
+ latest_data["bed_temperature"] = "N/A"
104
+ timeout = 10
105
+ logger.info("Waiting for response...")
106
+ while latest_data["bed_temperature"] == "N/A" and timeout > 0:
107
+ time.sleep(1)
108
+ timeout -= 1
109
+ logger.debug(f"Waiting... {timeout} seconds left")
110
+
111
+ if timeout <= 0:
112
+ logger.warning("Timeout waiting for response")
113
+ return ("Disconnected", "N/A", "N/A", "Timeout waiting for response")
114
+
115
+ logger.info(f"Got response: {latest_data}")
116
+ return (
117
+ latest_data["status"],
118
+ latest_data["bed_temperature"],
119
+ latest_data["nozzle_temperature"],
120
+ latest_data["update_time"]
121
+ )
122
 
123
+ def send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed):
124
  """发送打印参数到打印机"""
125
+ serial = DEFAULT_SERIAL # 使用默认序列号
126
  logger.info(f"Sending parameters to {serial}: nozzle={nozzle_temp}, bed={bed_temp}, speed={print_speed}, fan={fan_speed}")
127
  try:
128
  params = {
 
134
 
135
  request_topic = f"bambu_a1_mini/request/{serial}"
136
 
137
+ if client:
138
  client.publish(request_topic, json.dumps({
139
  'command': 'set_parameters',
140
  'parameters': params
 
187
  status = {
188
  "app": "running",
189
  "time": time.strftime("%Y-%m-%d %H:%M:%S"),
190
+ "mqtt_connected": client is not None,
191
  "latest_update": latest_data["update_time"]
192
  }
193
  logger.info(f"Health check: {status}")
194
  return status
195
 
196
  # API端点函数
197
+ def api_get_data():
198
  """API端点:获取状态"""
199
+ logger.info("API call: get_data")
200
  try:
201
+ return get_data()
202
  except Exception as e:
203
+ logger.error(f"Error in api_get_data: {e}")
204
  return ("Error", "N/A", "N/A", str(e))
205
 
206
+ def api_capture_frame(img=None):
207
  """API端点:获取图像"""
208
+ logger.info("API call: capture_frame")
209
  try:
210
  img = capture_image()
211
+ return img
212
  except Exception as e:
213
+ logger.error(f"Error in api_capture_frame: {e}")
214
  return None
215
 
216
+ def api_lambda(img=None, param_1=200, param_2=60, param_3=60, param_4=100):
217
+ """API端点:分析图像"""
218
+ logger.info("API call: lambda")
219
  try:
220
+ # 这里应该是实际的图像分析代码
221
+ # 目前返回占位数据
222
+ return (
223
+ img, # 分析结果图像
224
+ 0.05, # missing_rate
225
+ 0.03, # excess_rate
226
+ 0.02, # stringing_rate
227
+ 0.9, # uniformity_score
228
+ 0.85, # print_quality_score
229
+ 0.7, # print_speed_score
230
+ 0.8, # material_efficiency_score
231
+ 0.8, # total_performance_score
232
+ latest_data["status"] # printer_status
233
  )
234
  except Exception as e:
235
+ logger.error(f"Error in api_lambda: {e}")
236
+ return None
237
 
238
+ def api_send_print_parameters(nozzle_temp=200, bed_temp=60, print_speed=60, fan_speed=100):
239
+ """API端点:发送打印参数"""
240
+ logger.info(f"API call: send_print_parameters with nozzle={nozzle_temp}, bed={bed_temp}, speed={print_speed}, fan={fan_speed}")
241
  try:
242
+ return send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed)
243
  except Exception as e:
244
+ logger.error(f"Error in api_send_print_parameters: {e}")
245
+ return f"Error: {str(e)}"
 
 
 
 
 
 
 
 
 
 
246
 
247
  # 创建主界面
248
  with gr.Blocks(title="Bambu A1 Mini Print Control") as demo:
249
  gr.Markdown("# Bambu A1 Mini Print Control")
250
 
251
  with gr.Row():
 
252
  refresh_btn = gr.Button("Refresh Status")
253
 
254
  with gr.Row():
 
274
  # 连接按钮
275
  refresh_btn.click(
276
  fn=get_data,
 
277
  outputs=[current_status, current_bed_temp, current_nozzle_temp, last_update]
278
  )
279
 
 
284
 
285
  send_params_btn.click(
286
  fn=send_print_parameters,
287
+ inputs=[nozzle_temp, bed_temp, print_speed, fan_speed],
288
  outputs=[current_status]
289
  )
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  # 自动刷新线程
292
  def auto_refresh():
293
  """自动刷新状态的后台线程"""
 
296
  try:
297
  time.sleep(5)
298
  logger.debug("Auto-refreshing printer status")
299
+ status, bed_temp, nozzle_temp, update_time = get_data()
300
 
301
  # 更新UI
302
  current_status.update(value=status)
 
312
  # 启动应用
313
  if __name__ == "__main__":
314
  logger.info("Starting Bambu A1 Mini Print Control application")
 
 
315
 
316
+ # 定义API端点
317
+ demo.queue()
318
+
319
+ # 添加API端点
320
+ demo.launch(
321
+ show_error=True,
322
+ share=False,
323
+ server_name="0.0.0.0",
324
+ server_port=7860
325
+ )