mqtt_sniffer.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #!/usr/bin/env python3
  2. """MQTT Sniffer for Bambu Lab printers.
  3. Connects to a printer and logs all MQTT messages to capture the exact
  4. command format used by OrcaSlicer or Bambu Studio.
  5. Usage:
  6. python mqtt_sniffer.py <printer_ip> <serial_number> <access_code>
  7. Example:
  8. python mqtt_sniffer.py 192.168.1.100 0948BB540200427 12345678
  9. """
  10. import json
  11. import ssl
  12. import sys
  13. from datetime import datetime
  14. import paho.mqtt.client as mqtt
  15. def on_connect(client, userdata, flags, rc):
  16. """Called when connected to the MQTT broker."""
  17. if rc == 0:
  18. print(f"[{datetime.now().strftime('%H:%M:%S')}] Connected to printer!")
  19. serial = userdata["serial"]
  20. # Subscribe to all topics for this printer
  21. topic_report = f"device/{serial}/report"
  22. client.subscribe(topic_report)
  23. print(f"[{datetime.now().strftime('%H:%M:%S')}] Subscribed to: {topic_report}")
  24. print("-" * 80)
  25. print("Listening for MQTT messages... Press Ctrl+C to stop.")
  26. print("Now use OrcaSlicer to add a K-profile and the command will be logged here.")
  27. print("-" * 80)
  28. else:
  29. print(f"[{datetime.now().strftime('%H:%M:%S')}] Connection failed with code: {rc}")
  30. def on_message(client, userdata, msg):
  31. """Called when a message is received."""
  32. try:
  33. payload = json.loads(msg.payload.decode("utf-8"))
  34. # Check if this is an extrusion_cali related message
  35. is_cali_msg = False
  36. command = None
  37. if "print" in payload:
  38. command = payload["print"].get("command", "")
  39. if "extrusion_cali" in command:
  40. is_cali_msg = True
  41. # Always log calibration messages with full detail
  42. if is_cali_msg:
  43. print(f"\n{'=' * 80}")
  44. print(f"[{datetime.now().strftime('%H:%M:%S.%f')[:-3]}] *** CALIBRATION COMMAND: {command} ***")
  45. print(f"Topic: {msg.topic}")
  46. print("Full payload:")
  47. print(json.dumps(payload, indent=2))
  48. print(f"{'=' * 80}\n")
  49. else:
  50. # For other messages, just show a brief summary
  51. if "print" in payload:
  52. cmd = payload["print"].get("command", "unknown")
  53. # Skip noisy status messages
  54. if cmd not in ["push_status"]:
  55. print(f"[{datetime.now().strftime('%H:%M:%S')}] Command: {cmd}")
  56. except json.JSONDecodeError:
  57. print(f"[{datetime.now().strftime('%H:%M:%S')}] Non-JSON message on {msg.topic}")
  58. except Exception as e:
  59. print(f"[{datetime.now().strftime('%H:%M:%S')}] Error processing message: {e}")
  60. def on_disconnect(client, userdata, rc):
  61. """Called when disconnected from the MQTT broker."""
  62. print(f"[{datetime.now().strftime('%H:%M:%S')}] Disconnected with code: {rc}")
  63. def main():
  64. if len(sys.argv) != 4:
  65. print("Usage: python mqtt_sniffer.py <printer_ip> <serial_number> <access_code>")
  66. print("\nExample:")
  67. print(" python mqtt_sniffer.py 192.168.1.100 0948BB540200427 12345678")
  68. sys.exit(1)
  69. printer_ip = sys.argv[1]
  70. serial_number = sys.argv[2]
  71. access_code = sys.argv[3]
  72. print(f"Connecting to printer at {printer_ip}...")
  73. print(f"Serial: {serial_number}")
  74. # Create MQTT client
  75. client = mqtt.Client(userdata={"serial": serial_number})
  76. client.username_pw_set("bblp", access_code)
  77. # Configure TLS
  78. ssl_context = ssl.create_default_context()
  79. ssl_context.check_hostname = False
  80. ssl_context.verify_mode = ssl.CERT_NONE
  81. client.tls_set_context(ssl_context)
  82. # Set callbacks
  83. client.on_connect = on_connect
  84. client.on_message = on_message
  85. client.on_disconnect = on_disconnect
  86. try:
  87. client.connect(printer_ip, 8883, 60)
  88. client.loop_forever()
  89. except KeyboardInterrupt:
  90. print("\n\nStopping sniffer...")
  91. client.disconnect()
  92. except Exception as e:
  93. print(f"Error: {e}")
  94. sys.exit(1)
  95. if __name__ == "__main__":
  96. main()