Skip to content

Commit f1a6619

Browse files
authored
Merge pull request #115 from mchrisgm/handler
2 parents 7936135 + 840be88 commit f1a6619

5 files changed

Lines changed: 171 additions & 9 deletions

File tree

bambulabs_api/mqtt_client.py

Lines changed: 116 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
import ssl
66
import datetime
7-
from typing import Any, Callable
7+
from typing import Any, Callable, Union
88
from re import match
99

1010
import paho.mqtt.client as mqtt
@@ -13,12 +13,24 @@
1313
from paho.mqtt.enums import CallbackAPIVersion
1414

1515
from bambulabs_api.ams import AMS, AMSHub
16-
from bambulabs_api.printer_info import NozzleType
16+
from bambulabs_api.printer_info import (
17+
NozzleType,
18+
PrinterFirmwareInfo,
19+
PrinterType)
1720

1821
from .filament_info import Filament, FilamentTray
1922
from .states_info import GcodeState, PrintStatus
2023

2124

25+
def set_temperature_support(printer_info: PrinterFirmwareInfo):
26+
printer_type = printer_info.printer_type
27+
if printer_type in (PrinterType.P1P, PrinterType.P1S,
28+
PrinterType.X1E, PrinterType.X1C, ):
29+
return printer_info.firmware_version < "01.06"
30+
elif printer_type in (PrinterType.A1, PrinterType.A1_MINI):
31+
return printer_info.firmware_version <= "01.04"
32+
33+
2234
def is_valid_gcode(line: str):
2335
"""
2436
Check if a line is a valid G-code command
@@ -83,6 +95,30 @@ def __init__(
8395

8496
self._client.on_connect = self._on_connect
8597
self._client.on_message = self._on_message
98+
self._client.on_disconnect = self._on_disconnect
99+
100+
self.on_connect_handler: Callable[[
101+
'PrinterMQTTClient',
102+
mqtt.Client,
103+
Any,
104+
mqtt.ConnectFlags,
105+
paho.mqtt.reasoncodes.ReasonCode,
106+
paho.mqtt.properties.Properties | None
107+
], None] = lambda a, b, c, d, e, f: None
108+
self.on_message_handler: Callable[[
109+
'PrinterMQTTClient',
110+
mqtt.Client,
111+
Any,
112+
mqtt.MQTTMessage
113+
], None] = lambda a, b, c, d: None
114+
self.on_disconnect_handler: Callable[[
115+
'PrinterMQTTClient',
116+
mqtt.Client,
117+
Any,
118+
mqtt.DisconnectFlags,
119+
paho.mqtt.reasoncodes.ReasonCode,
120+
Union[paho.mqtt.properties.Properties, None],
121+
], None] = lambda a, b, c, d, e, f: None
86122

87123
self.pushall_timeout: int = pushall_timeout
88124
self.pushall_aggressive = pushall_on_connect
@@ -95,6 +131,11 @@ def __init__(
95131
self.ams_hub: AMSHub = AMSHub()
96132
self.strict = strict
97133

134+
self.printer_info: PrinterFirmwareInfo = PrinterFirmwareInfo(
135+
PrinterType.P1S,
136+
"01.04.00.00"
137+
)
138+
98139
def is_connected(self):
99140
"""
100141
Check if the mqtt client is connected
@@ -123,6 +164,24 @@ def wrapper(
123164
def ready(self) -> bool:
124165
return bool(self._data)
125166

167+
def _on_disconnect(
168+
self,
169+
client: mqtt.Client,
170+
userdata: Any,
171+
disconnect_flags: mqtt.DisconnectFlags,
172+
reason_code: paho.mqtt.reasoncodes.ReasonCode,
173+
properties: Union[paho.mqtt.properties.Properties, None],
174+
) -> None:
175+
logging.info(f"Client Disconnected: {client} {userdata} "
176+
f"{disconnect_flags} {reason_code} {properties}")
177+
self.on_disconnect_handler(
178+
self,
179+
client,
180+
userdata,
181+
disconnect_flags,
182+
reason_code,
183+
properties)
184+
126185
def _on_message(
127186
self,
128187
client: mqtt.Client,
@@ -133,6 +192,8 @@ def _on_message(
133192
doc = json.loads(msg.payload)
134193
self.manual_update(doc)
135194

195+
self.on_message_handler(self, client, userdata, msg)
196+
136197
def manual_update(self, doc: dict[str, Any]) -> None:
137198
if "print" in doc:
138199
self._data |= doc["print"]
@@ -173,6 +234,15 @@ def _on_connect(
173234
else:
174235
logging.warning(f"Connection failed with result code {rc}")
175236

237+
self.on_connect_handler(
238+
self,
239+
client,
240+
userdata,
241+
flags,
242+
rc,
243+
properties
244+
)
245+
176246
def connect(self) -> None:
177247
"""
178248
Connects to the MQTT server asynchronously
@@ -485,17 +555,35 @@ def send_gcode(
485555
raise ValueError("Invalid G-code command")
486556
return self.__send_gcode_line("\n".join(gcode_command))
487557

488-
def set_bed_temperature(self, temperature: int) -> bool:
558+
def set_bed_temperature(
559+
self,
560+
temperature: int,
561+
override: bool = False
562+
) -> bool:
489563
"""
490-
Set the bed temperature
564+
Set the bed temperature. Note P1 firmware version above 01.06 does not
565+
support M140. M190 is used instead (set and wait for temperature).
566+
To prevent long wait times, if temperature is set to below 40 deg cel,
567+
no temperature is set, override flag is provided to circumvent this.
491568
492569
Args:
493570
temperature (int): The temperature to set the bed to
571+
override (bool): Whether to override guards. Default to False
494572
495573
Returns:
496574
bool: success of setting the bed temperature
497575
"""
498-
return self.__send_gcode_line(f"M140 S{temperature}\n")
576+
if set_temperature_support(self.printer_info):
577+
return self.__send_gcode_line(f"M140 S{temperature}\n")
578+
else:
579+
if temperature < 40 and not override:
580+
logging.warning(
581+
"Attempting to set low bed temperature not recommended. "
582+
"Set override flag to true to if you're sure you want to "
583+
f"run M190 S{temperature};"
584+
)
585+
return False
586+
return self.__send_gcode_line(f"M190 S{temperature}\n")
499587

500588
def get_fan_gear(self):
501589
"""
@@ -644,17 +732,37 @@ def set_print_speed_lvl(self, speed_lvl: int = 1) -> bool:
644732
{"print": {"command": "print_speed", "param": f"{speed_lvl}"}}
645733
)
646734

647-
def set_nozzle_temperature(self, temperature: int) -> bool:
735+
def set_nozzle_temperature(
736+
self,
737+
temperature: int,
738+
override: bool = False
739+
) -> bool:
648740
"""
649-
Set the nozzle temperature
741+
Set the nozzle temperature. Note P1 firmware version above 01.06 does
742+
not support M104. M109 is used instead (set and wait for temperature).
743+
To prevent long wait times, if temperature is set to below 40 deg cel,
744+
no temperature is set, override flag is provided to circumvent this.
650745
746+
Args:
747+
temperature (int): The temperature to set the bed to
748+
override (bool): Whether to override guards. Default to False
651749
Args:
652750
temperature (int): temperature to set the nozzle to
653751
654752
Returns:
655753
bool: success of setting the nozzle temperature
656754
"""
657-
return self.__send_gcode_line(f"M104 S{temperature}\n")
755+
if set_temperature_support(self.printer_info):
756+
return self.__send_gcode_line(f"M104 S{temperature}\n")
757+
else:
758+
if temperature < 60 and not override:
759+
logging.warning(
760+
"Attempting to set low bed temperature not recommended. "
761+
"Set override flag to true to if you're sure you want to "
762+
f"run M109 S{temperature};"
763+
)
764+
return False
765+
return self.__send_gcode_line(f"M109 S{temperature}\n")
658766

659767
def set_printer_filament(
660768
self,

bambulabs_api/printer_info.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
__all__ = [
2+
"NozzleType",
3+
"P1FirmwareVersion",
4+
]
5+
6+
from dataclasses import dataclass
17
from enum import Enum
28

39
NOZZLE_DIAMETER = {
@@ -8,6 +14,45 @@
814
}
915

1016

17+
class PrinterType(str, Enum):
18+
"""
19+
Enum class for the printer type
20+
21+
Attributes
22+
----------
23+
P1S: P1S printer
24+
P1P: P1P printer
25+
A1: A1P printer
26+
A1_MINI: A1_MINI printer
27+
X1C: X1C printer
28+
X1E: X1E printer
29+
"""
30+
P1S = "P1S"
31+
P1P = "P1P"
32+
A1 = "A1"
33+
A1_MINI = "A1_MINI"
34+
X1C = "X1C"
35+
X1E = "X1E"
36+
37+
38+
@dataclass
39+
class PrinterFirmwareInfo:
40+
printer_type: PrinterType
41+
firmware_version: str
42+
43+
44+
class P1FirmwareVersion(str, Enum):
45+
V_01_07_00_00 = "01.07.00.00"
46+
V_01_06_01_02 = "01.06.01.02"
47+
V_01_06_01_00 = "01.06.01.00"
48+
V_01_06_00_00 = "01.06.00.00"
49+
V_01_05_02_00 = "01.05.02.00"
50+
V_01_05_01_00 = "01.05.01.00"
51+
V_01_04_02_00 = "01.04.02.00"
52+
V_01_04_01_00 = "01.04.01.00"
53+
V_01_04_00_00 = "01.04.00.00"
54+
55+
1156
class NozzleType(str, Enum):
1257
"""
1358
Enum class for the nozzle type

docs/release.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Release notes for each release here:
77
.. toctree::
88
:maxdepth: 1
99

10+
2.5.12 <release/2.5.12-notes.rst>
1011
2.5.10 <release/2.5.10-notes.rst>
1112
2.5.9 <release/2.5.9-notes.rst>
1213
2.5.8 <release/2.5.8-notes.rst>

docs/release/2.5.12-notes.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Bambulabs API 2.5.12 Release Notes
2+
==================================
3+
4+
* Add workaround for setting temperature for P1S
5+
* Add get fan speeds by [@Stephen Tafoya](https://github.com/YOUR-WORST-TACO)
6+
* Updated print 3mf api to accept custom filepaths - updated print gcode example scripts
7+
* Add gcode validation bypass
8+
* Add mqtt on_message, on_connect, and on_disconnect handlers

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "bambulabs_api"
7-
version = "2.5.12-rc1"
7+
version = "2.5.12"
88
authors = [
99
{ name="Chris Ioannidis", email="chris.ioannidis23@imperial.ac.uk" },
1010
{ name="Haotian Wu", email="64962148+ohmdelta@users.noreply.github.com"}

0 commit comments

Comments
 (0)