circuitpython-bambulabs 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bambulabs.py +306 -0
- circuitpython_bambulabs-1.0.0.dist-info/METADATA +222 -0
- circuitpython_bambulabs-1.0.0.dist-info/RECORD +6 -0
- circuitpython_bambulabs-1.0.0.dist-info/WHEEL +5 -0
- circuitpython_bambulabs-1.0.0.dist-info/licenses/LICENSE +21 -0
- circuitpython_bambulabs-1.0.0.dist-info/top_level.txt +1 -0
bambulabs.py
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
|
|
2
|
+
# SPDX-FileCopyrightText: Copyright (c) 2026 Paul Cutler
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
"""
|
|
6
|
+
`bambulabs`
|
|
7
|
+
================================================================================
|
|
8
|
+
|
|
9
|
+
A library to interface with a Bambu Labs 3D printer and query status.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* Author(s): Paul Cutler
|
|
13
|
+
|
|
14
|
+
Implementation Notes
|
|
15
|
+
--------------------
|
|
16
|
+
|
|
17
|
+
**Hardware:**
|
|
18
|
+
|
|
19
|
+
Requires a Bambu Labs 3D printer and Bambu Labs Makerworld account.
|
|
20
|
+
|
|
21
|
+
**Software and Dependencies:**
|
|
22
|
+
|
|
23
|
+
* Adafruit CircuitPython firmware for the supported boards:
|
|
24
|
+
https://circuitpython.org/downloads
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
import time
|
|
30
|
+
|
|
31
|
+
import adafruit_connection_manager
|
|
32
|
+
import adafruit_minimqtt.adafruit_minimqtt as MQTT
|
|
33
|
+
import wifi
|
|
34
|
+
|
|
35
|
+
__version__ = "1.0.0"
|
|
36
|
+
__repo__ = "https://github.com/prcutler/CircuitPython_bambulabs.git"
|
|
37
|
+
|
|
38
|
+
# BAMBU MQTT settings - Bambu Cloud
|
|
39
|
+
BAMBU_BROKER = os.getenv("BAMBU_BROKER")
|
|
40
|
+
ACCESS_TOKEN = os.getenv("BAMBU_ACCESS_TOKEN")
|
|
41
|
+
USER_ID = os.getenv("USER_ID")
|
|
42
|
+
BAMBU_IP = os.getenv("BAMBU_IP")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class PrinterStatus:
|
|
46
|
+
"""Wraps the raw JSON dict returned by a ``pushall`` response and exposes
|
|
47
|
+
each printer field as a named, readable property.
|
|
48
|
+
|
|
49
|
+
All values come from the snapshot captured at the time ``pushall`` was
|
|
50
|
+
called. Use :attr:`raw` to access the complete original dict.
|
|
51
|
+
|
|
52
|
+
:param data: The raw JSON dict received from the printer's report topic.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, data):
|
|
56
|
+
self._data = data
|
|
57
|
+
self._print = data.get("print", {})
|
|
58
|
+
self._info = data.get("info", {})
|
|
59
|
+
self._system = data.get("system", {})
|
|
60
|
+
self._upgrade = data.get("upgrade", {})
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def raw(self):
|
|
64
|
+
"""The complete raw JSON dict from the printer."""
|
|
65
|
+
return self._data
|
|
66
|
+
|
|
67
|
+
# ---- Print state -------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def gcode_state(self):
|
|
71
|
+
"""Printer gcode state string (e.g. ``RUNNING``, ``PAUSE``, ``FINISH``)."""
|
|
72
|
+
return self._print.get("gcode_state")
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def print_percentage(self):
|
|
76
|
+
"""Current print completion percentage (0–100)."""
|
|
77
|
+
return self._print.get("mc_percent")
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def remaining_time(self):
|
|
81
|
+
"""Estimated remaining print time in minutes."""
|
|
82
|
+
return self._print.get("mc_remaining_time")
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def current_layer(self):
|
|
86
|
+
"""Current layer number being printed."""
|
|
87
|
+
return self._print.get("layer_num")
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def total_layers(self):
|
|
91
|
+
"""Total number of layers in the print job."""
|
|
92
|
+
return self._print.get("total_layer_num")
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def gcode_file(self):
|
|
96
|
+
"""Filename of the currently active gcode file."""
|
|
97
|
+
return self._print.get("gcode_file")
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def subtask_name(self):
|
|
101
|
+
"""Current print subtask / job name."""
|
|
102
|
+
return self._print.get("subtask_name")
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def print_speed(self):
|
|
106
|
+
"""Print speed level (0=silent, 1=standard, 2=sport, 3=ludicrous)."""
|
|
107
|
+
return self._print.get("spd_lvl")
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def print_error_code(self):
|
|
111
|
+
"""Current print error code, or ``0`` if none."""
|
|
112
|
+
return self._print.get("print_error")
|
|
113
|
+
|
|
114
|
+
# ---- Temperatures ------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def nozzle_temperature(self):
|
|
118
|
+
"""Current nozzle temperature in degrees Celsius."""
|
|
119
|
+
return self._print.get("nozzle_temper")
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def nozzle_temperature_target(self):
|
|
123
|
+
"""Target nozzle temperature in degrees Celsius."""
|
|
124
|
+
return self._print.get("nozzle_target_temper")
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def bed_temperature(self):
|
|
128
|
+
"""Current bed temperature in degrees Celsius."""
|
|
129
|
+
return self._print.get("bed_temper")
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def bed_temperature_target(self):
|
|
133
|
+
"""Target bed temperature in degrees Celsius."""
|
|
134
|
+
return self._print.get("bed_target_temper")
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def chamber_temperature(self):
|
|
138
|
+
"""Current chamber temperature in degrees Celsius."""
|
|
139
|
+
return self._print.get("chamber_temper")
|
|
140
|
+
|
|
141
|
+
# ---- Fan speeds --------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def part_fan_speed(self):
|
|
145
|
+
"""Part cooling fan speed (0–255)."""
|
|
146
|
+
return self._print.get("cooling_fan_speed")
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def aux_fan_speed(self):
|
|
150
|
+
"""Auxiliary fan speed (0–255)."""
|
|
151
|
+
return self._print.get("big_fan1_speed")
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def chamber_fan_speed(self):
|
|
155
|
+
"""Chamber fan speed (0–255)."""
|
|
156
|
+
return self._print.get("big_fan2_speed")
|
|
157
|
+
|
|
158
|
+
# ---- Nozzle ------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def nozzle_type(self):
|
|
162
|
+
"""Installed nozzle type string (e.g. ``"brass"``)."""
|
|
163
|
+
return self._print.get("nozzle_type")
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def nozzle_diameter(self):
|
|
167
|
+
"""Installed nozzle diameter in mm."""
|
|
168
|
+
return self._print.get("nozzle_diameter")
|
|
169
|
+
|
|
170
|
+
# ---- Filament / AMS ----------------------------------------------------
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def ams_status(self):
|
|
174
|
+
"""AMS filament / tray status dict, or ``None`` if no AMS present."""
|
|
175
|
+
return self._print.get("ams")
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def vt_tray(self):
|
|
179
|
+
"""External spool (virtual tray) properties dict."""
|
|
180
|
+
return self._print.get("vt_tray")
|
|
181
|
+
|
|
182
|
+
# ---- System ------------------------------------------------------------
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def wifi_signal(self):
|
|
186
|
+
"""WiFi signal strength string (e.g. ``"-45dBm"``)."""
|
|
187
|
+
return self._print.get("wifi_signal")
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def light_state(self):
|
|
191
|
+
"""Chamber light state list from the system ``lights_report`` field."""
|
|
192
|
+
return self._system.get("lights_report")
|
|
193
|
+
|
|
194
|
+
# ---- Firmware ----------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def firmware_version(self):
|
|
198
|
+
"""Current OTA firmware version string, or ``None`` if not present."""
|
|
199
|
+
modules = self._info.get("module", [])
|
|
200
|
+
for module in modules:
|
|
201
|
+
if isinstance(module, dict) and module.get("name") == "ota":
|
|
202
|
+
return module.get("sw_ver")
|
|
203
|
+
return None
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class BambuPrinter:
|
|
207
|
+
"""Connect to a Bambu Labs printer over MQTT and query its status.
|
|
208
|
+
|
|
209
|
+
:param mqtt_client: A configured ``adafruit_minimqtt.MQTT`` instance.
|
|
210
|
+
:param serial_number: The printer's serial number, used to build MQTT topics.
|
|
211
|
+
:param response_timeout: Seconds to wait for a printer response (default 10).
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
def __init__(self, serial_number, response_timeout=10):
|
|
215
|
+
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
|
|
216
|
+
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
|
|
217
|
+
|
|
218
|
+
# Set up MQTT client
|
|
219
|
+
mqtt_client = MQTT.MQTT(
|
|
220
|
+
broker=BAMBU_BROKER,
|
|
221
|
+
port=8883,
|
|
222
|
+
username=USER_ID,
|
|
223
|
+
password=ACCESS_TOKEN,
|
|
224
|
+
socket_pool=pool,
|
|
225
|
+
ssl_context=ssl_context,
|
|
226
|
+
is_ssl=True,
|
|
227
|
+
)
|
|
228
|
+
self._mqtt = mqtt_client
|
|
229
|
+
self._serial = serial_number
|
|
230
|
+
self._response_timeout = response_timeout
|
|
231
|
+
self._report_topic = f"device/{serial_number}/report"
|
|
232
|
+
self._request_topic = f"device/{serial_number}/request"
|
|
233
|
+
self._last_response = None
|
|
234
|
+
|
|
235
|
+
self._mqtt.on_connect = self._on_connect
|
|
236
|
+
self._mqtt.on_message = self._on_message
|
|
237
|
+
|
|
238
|
+
# ---- Internal ----------------------------------------------------------
|
|
239
|
+
|
|
240
|
+
def _on_connect(self, client, _userdata, _flags, _rc):
|
|
241
|
+
client.subscribe(self._report_topic)
|
|
242
|
+
|
|
243
|
+
def _on_message(self, _client, _topic, message):
|
|
244
|
+
try:
|
|
245
|
+
data = json.loads(message)
|
|
246
|
+
except Exception:
|
|
247
|
+
return
|
|
248
|
+
self._last_response = data
|
|
249
|
+
|
|
250
|
+
def _send_and_wait(self, payload):
|
|
251
|
+
"""Publish *payload* and block until the printer responds or timeout.
|
|
252
|
+
|
|
253
|
+
:returns: The raw JSON response dict, or ``None`` on timeout.
|
|
254
|
+
"""
|
|
255
|
+
self._last_response = None
|
|
256
|
+
self._mqtt.publish(self._request_topic, json.dumps(payload))
|
|
257
|
+
deadline = time.monotonic() + self._response_timeout
|
|
258
|
+
while self._last_response is None and time.monotonic() < deadline:
|
|
259
|
+
self._mqtt.loop()
|
|
260
|
+
time.sleep(0.05)
|
|
261
|
+
return self._last_response
|
|
262
|
+
|
|
263
|
+
# ---- Connection --------------------------------------------------------
|
|
264
|
+
|
|
265
|
+
def connect(self):
|
|
266
|
+
"""Establish the MQTT connection to the printer."""
|
|
267
|
+
print(f"Connecting to Bambu printer at {BAMBU_IP}...")
|
|
268
|
+
self._mqtt.connect()
|
|
269
|
+
|
|
270
|
+
def loop(self):
|
|
271
|
+
"""Process pending MQTT messages. Call regularly in your main loop."""
|
|
272
|
+
self._mqtt.loop()
|
|
273
|
+
|
|
274
|
+
def loop_forever(self):
|
|
275
|
+
"""Block and loop indefinitely, processing MQTT messages."""
|
|
276
|
+
self._mqtt.loop_forever()
|
|
277
|
+
|
|
278
|
+
def is_connected(self):
|
|
279
|
+
"""Return ``True`` if the MQTT client is currently connected."""
|
|
280
|
+
return self._mqtt.is_connected()
|
|
281
|
+
|
|
282
|
+
# ---- Queries -----------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
def pushall(self):
|
|
285
|
+
"""Request a full state snapshot from the printer.
|
|
286
|
+
|
|
287
|
+
:returns: A :class:`PrinterStatus` instance, or ``None`` on timeout.
|
|
288
|
+
"""
|
|
289
|
+
response = self._send_and_wait({"pushing": {"command": "pushall"}})
|
|
290
|
+
if response is not None:
|
|
291
|
+
return PrinterStatus(response)
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
def get_version(self):
|
|
295
|
+
"""Request hardware and firmware version information.
|
|
296
|
+
|
|
297
|
+
:returns: The raw JSON response dict, or ``None`` on timeout.
|
|
298
|
+
"""
|
|
299
|
+
return self._send_and_wait({"info": {"sequence_id": "0", "command": "get_version"}})
|
|
300
|
+
|
|
301
|
+
def get_firmware_history(self):
|
|
302
|
+
"""Request the firmware version history.
|
|
303
|
+
|
|
304
|
+
:returns: The raw JSON response dict, or ``None`` on timeout.
|
|
305
|
+
"""
|
|
306
|
+
return self._send_and_wait({"upgrade": {"sequence_id": "0", "command": "get_history"}})
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: circuitpython-bambulabs
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A library to interface with a Bambu Labs 3D printer and query status and information
|
|
5
|
+
Author-email: Paul Cutler <paul@paulcutler.org>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/prcutler/CircuitPython_bambulabs
|
|
8
|
+
Keywords: adafruit,blinka,circuitpython,micropython,bambulabs,mqtt,circuitpython,bambulabs
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
11
|
+
Classifier: Topic :: Software Development :: Embedded Systems
|
|
12
|
+
Classifier: Topic :: System :: Hardware
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Description-Content-Type: text/x-rst
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: Adafruit-Blinka
|
|
17
|
+
Requires-Dist: Adafruit_CircuitPython_MiniMQTT
|
|
18
|
+
Provides-Extra: optional
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
Introduction
|
|
22
|
+
============
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
.. image:: https://readthedocs.org/projects/circuitpython-bambulabs/badge/?version=latest
|
|
26
|
+
:target: https://circuitpython-bambulabs.readthedocs.io/
|
|
27
|
+
:alt: Documentation Status
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
.. image:: https://img.shields.io/discord/327254708534116352.svg
|
|
32
|
+
:target: https://adafru.it/discord
|
|
33
|
+
:alt: Discord
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
.. image:: https://github.com/prcutler/CircuitPython_bambulabs/workflows/Build%20CI/badge.svg
|
|
37
|
+
:target: https://github.com/prcutler/CircuitPython_bambulabs/actions
|
|
38
|
+
:alt: Build Status
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
|
42
|
+
:target: https://github.com/astral-sh/ruff
|
|
43
|
+
:alt: Code Style: Ruff
|
|
44
|
+
|
|
45
|
+
A library to interface with a Bambu Labs 3D printer and query status and information
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Dependencies
|
|
49
|
+
=============
|
|
50
|
+
This driver depends on:
|
|
51
|
+
|
|
52
|
+
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
|
|
53
|
+
* `Adafruit_CircuitPython_MiniMQTT <https://github.com/adafruit/Adafruit_CircuitPython_MiniMQTT/>`_
|
|
54
|
+
|
|
55
|
+
Please ensure all dependencies are available on the CircuitPython filesystem.
|
|
56
|
+
This is easily achieved by downloading
|
|
57
|
+
`the Adafruit library and driver bundle <https://circuitpython.org/libraries>`_
|
|
58
|
+
or individual libraries can be installed using
|
|
59
|
+
`circup <https://github.com/adafruit/circup>`_.
|
|
60
|
+
|
|
61
|
+
Installing from PyPI
|
|
62
|
+
=====================
|
|
63
|
+
.. note:: This library is not available on PyPI yet. Install documentation is included
|
|
64
|
+
as a standard element. Stay tuned for PyPI availability!
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
|
|
68
|
+
PyPI <https://pypi.org/project/circuitpython-bambulabs/>`_.
|
|
69
|
+
To install for current user:
|
|
70
|
+
|
|
71
|
+
.. code-block:: shell
|
|
72
|
+
|
|
73
|
+
pip3 install circuitpython-bambulabs
|
|
74
|
+
|
|
75
|
+
To install system-wide (this may be required in some cases):
|
|
76
|
+
|
|
77
|
+
.. code-block:: shell
|
|
78
|
+
|
|
79
|
+
sudo pip3 install circuitpython-bambulabs
|
|
80
|
+
|
|
81
|
+
To install in a virtual environment in your current project:
|
|
82
|
+
|
|
83
|
+
.. code-block:: shell
|
|
84
|
+
|
|
85
|
+
mkdir project-name && cd project-name
|
|
86
|
+
python3 -m venv .venv
|
|
87
|
+
source .env/bin/activate
|
|
88
|
+
pip3 install circuitpython-bambulabs
|
|
89
|
+
|
|
90
|
+
Installing to a Connected CircuitPython Device with Circup
|
|
91
|
+
==========================================================
|
|
92
|
+
|
|
93
|
+
Make sure that you have ``circup`` installed in your Python environment.
|
|
94
|
+
Install it with the following command if necessary:
|
|
95
|
+
|
|
96
|
+
.. code-block:: shell
|
|
97
|
+
|
|
98
|
+
pip3 install circup
|
|
99
|
+
|
|
100
|
+
With ``circup`` installed and your CircuitPython device connected use the
|
|
101
|
+
following command to install:
|
|
102
|
+
|
|
103
|
+
.. code-block:: shell
|
|
104
|
+
|
|
105
|
+
circup install bambulabs
|
|
106
|
+
|
|
107
|
+
Or the following command to update an existing version:
|
|
108
|
+
|
|
109
|
+
.. code-block:: shell
|
|
110
|
+
|
|
111
|
+
circup update
|
|
112
|
+
|
|
113
|
+
Obtaining Your Printer Credentials and Save in settings.toml
|
|
114
|
+
============================================================
|
|
115
|
+
|
|
116
|
+
#. Login to `MakerWorld <https://makerworld.com/>`_.
|
|
117
|
+
#. Open the dev-tools (F12 in most browsers) and select
|
|
118
|
+
``Application > Cookies > https://makerworld.com``.
|
|
119
|
+
#. Copy the ``token`` string and save it as ``BAMBU_ACCESS_TOKEN`` in ``settings.toml``.
|
|
120
|
+
#. Access `https://makerworld.com/api/v1/design-user-service/my/preference
|
|
121
|
+
<https://makerworld.com/api/v1/design-user-service/my/preference>`_ and copy
|
|
122
|
+
``uid`` as ``USER_ID``.
|
|
123
|
+
#. Access `https://makerworld.com/api/v1/iot-service/api/user/bind
|
|
124
|
+
<https://makerworld.com/api/v1/iot-service/api/user/bind>`_ and copy
|
|
125
|
+
``dev_id`` as ``DEVICE_ID``.
|
|
126
|
+
#. On your printer, go to Settings and obtain the IP address and copy it as
|
|
127
|
+
``BAMBU_IP``.
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
You will need a ``settings.toml`` file with the following to connect via MQTT:
|
|
131
|
+
|
|
132
|
+
* CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
|
|
133
|
+
* CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
|
|
134
|
+
* BAMBU_BROKER = os.getenv("BAMBU_BROKER")
|
|
135
|
+
* ACCESS_TOKEN = os.getenv("BAMBU_ACCESS_TOKEN")
|
|
136
|
+
* USER_ID = os.getenv("USER_ID")
|
|
137
|
+
* DEVICE_ID = "your_printer_serial_number"
|
|
138
|
+
* BAMBU_IP = "your_printer_IP_address"
|
|
139
|
+
|
|
140
|
+
Misc. information
|
|
141
|
+
=================
|
|
142
|
+
|
|
143
|
+
This library queries your Bambu Labs 3D printer via the Bambu Cloud using MQTT 5.0.
|
|
144
|
+
Local mode is not supported due to it using MQTT 3.1.1. Issuing commands to your
|
|
145
|
+
Bambu printer is out of scope for this library.
|
|
146
|
+
|
|
147
|
+
Usage Example
|
|
148
|
+
=============
|
|
149
|
+
|
|
150
|
+
.. code-block:: python
|
|
151
|
+
|
|
152
|
+
import json
|
|
153
|
+
import os
|
|
154
|
+
|
|
155
|
+
import wifi
|
|
156
|
+
|
|
157
|
+
import bambulabs as bl
|
|
158
|
+
|
|
159
|
+
# You will need a settings.toml file with the following to connect via MQTT:
|
|
160
|
+
# bambu_broker = os.getenv("BAMBU_BROKER")
|
|
161
|
+
# access_token = os.getenv("BAMBU_ACCESS_TOKEN")
|
|
162
|
+
# user_id = os.getenv("USER_ID")
|
|
163
|
+
# DEVICE_ID = "your_printer_serial_number"
|
|
164
|
+
|
|
165
|
+
# Set up networking
|
|
166
|
+
print("Connecting to AP...")
|
|
167
|
+
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
|
|
168
|
+
print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}")
|
|
169
|
+
print(f"My IP address: {wifi.radio.ipv4_address}")
|
|
170
|
+
|
|
171
|
+
device_id = os.getenv("DEVICE_ID")
|
|
172
|
+
|
|
173
|
+
printer = bl.BambuPrinter(bl.BambuPrinter.__init__, device_id)
|
|
174
|
+
printer.connect()
|
|
175
|
+
|
|
176
|
+
status = printer.pushall()
|
|
177
|
+
|
|
178
|
+
if status is None:
|
|
179
|
+
print("Timed out waiting for pushall response.")
|
|
180
|
+
else:
|
|
181
|
+
# Print out each individual status
|
|
182
|
+
print("--- Printer Status ---")
|
|
183
|
+
print(f"State: {status.gcode_state}")
|
|
184
|
+
print(f"File: {status.gcode_file}")
|
|
185
|
+
print(f"Job: {status.subtask_name}")
|
|
186
|
+
print(f"Progress: {status.print_percentage}%")
|
|
187
|
+
print(f"Remaining: {status.remaining_time} min")
|
|
188
|
+
print(f"Layer: {status.current_layer} / {status.total_layers}")
|
|
189
|
+
print(f"Print speed: {status.print_speed}")
|
|
190
|
+
print(f"Print error: {status.print_error_code}")
|
|
191
|
+
print(f"Nozzle temp: {status.nozzle_temperature} / {status.nozzle_temperature_target} C")
|
|
192
|
+
print(f"Bed temp: {status.bed_temperature} / {status.bed_temperature_target} C")
|
|
193
|
+
print(f"Chamber temp: {status.chamber_temperature} C")
|
|
194
|
+
print(f"Part fan: {status.part_fan_speed}")
|
|
195
|
+
print(f"Aux fan: {status.aux_fan_speed}")
|
|
196
|
+
print(f"Chamber fan: {status.chamber_fan_speed}")
|
|
197
|
+
print(f"Nozzle type: {status.nozzle_type}")
|
|
198
|
+
print(f"Nozzle diameter: {status.nozzle_diameter} mm")
|
|
199
|
+
print(f"WiFi signal: {status.wifi_signal}")
|
|
200
|
+
print(f"Light state: {status.light_state}")
|
|
201
|
+
print(f"Firmware version: {status.firmware_version}")
|
|
202
|
+
print()
|
|
203
|
+
# Print the entire JSON response
|
|
204
|
+
print("--- Raw JSON ---")
|
|
205
|
+
print(json.dumps(status.raw))
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
Documentation
|
|
209
|
+
=============
|
|
210
|
+
API documentation for this library can be found on `Read the Docs <https://circuitpython-bambulabs.readthedocs.io/>`_.
|
|
211
|
+
|
|
212
|
+
For information on building library documentation, please check out
|
|
213
|
+
`this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
|
|
214
|
+
|
|
215
|
+
Contributing
|
|
216
|
+
============
|
|
217
|
+
|
|
218
|
+
Contributions are welcome! Please read our `Code of Conduct
|
|
219
|
+
<https://github.com/prcutler/CircuitPython_bambulabs/blob/HEAD/CODE_OF_CONDUCT.md>`_
|
|
220
|
+
before contributing to help this project stay welcoming.
|
|
221
|
+
|
|
222
|
+
This library was created with the assistance of Claude. (I know, I know...)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
bambulabs.py,sha256=g0kfTNGWUyHECH-tOj9TGPm1OwgKwHYQ0yhU_uDmle8,9928
|
|
2
|
+
circuitpython_bambulabs-1.0.0.dist-info/licenses/LICENSE,sha256=Maocfq0E-T2QKRxYKgtMbI4CSXO7GocYugv1-V3NJ7E,1078
|
|
3
|
+
circuitpython_bambulabs-1.0.0.dist-info/METADATA,sha256=JC09RhXCQCMoRhj526FrM-_v5alZNYR0s5aJXKhxDWc,8017
|
|
4
|
+
circuitpython_bambulabs-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
circuitpython_bambulabs-1.0.0.dist-info/top_level.txt,sha256=xZ8f7rtBtbUvYUfd7CMbLvyPgntgnNLcTUz4kQRRDQs,10
|
|
6
|
+
circuitpython_bambulabs-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Paul Cutler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bambulabs
|