44import logging
55import ssl
66import datetime
7- from typing import Any , Callable
7+ from typing import Any , Callable , Union
88from re import match
99
1010import paho .mqtt .client as mqtt
1313from paho .mqtt .enums import CallbackAPIVersion
1414
1515from 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
1821from .filament_info import Filament , FilamentTray
1922from .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+
2234def 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 ,
0 commit comments