Skip to content

bambutools

bambutools contains a collection of methods used as tools (mostly internal).

Classes:

Name Description
AMSControlCommand

AMS Control Commands enum

AMSDryFanStatus

AMS drying fan status extracted from bits 18-21 of ams_info.

AMSDrySubStatus

AMS drying sub-status extracted from bits 22-25 of ams_info.

AMSHeatingState

AMS Drying/Heater states extracted from bits 4-7 of ams_info.

AMSModel

AMS model enum

AMSSeries

AMS Series enum

AMSUserSetting

AMS User Settings enum

ActiveTool

The currently active extruder index.

AirConditioningMode

The mode the printer's air conditioning sub system is in.

DetectorSensitivity

Sensitivity level for X-Cam AI vision detectors (spaghetti, pile-up, clump, air-print).

ExtruderInfoState

Consolidated logical states for extruder sensor status.

ExtruderStatus

Operational states for physical extruders.

NozzleDiameter

Nozzle Diameter enum

NozzleFlowType

Canonical nozzle flow families used by BambuStudio/Orca nozzle identifiers.

NozzleMaterialCode

Canonical material codes used in encoded nozzle identifiers.

NozzleType

Canonical cross-model nozzle material type from telemetry.

PlateType

Used by BambuPrinter.print_3mf_file to specify which plate should be used when

PrintOption

Print Option enum

PrinterModel

Printer model enum

PrinterSeries

Printer Series enum

ServiceState

This enum is used by bambu-printer-manager to track the underlying state

TrayState

Operational status of the filament tray.

Functions:

Name Description
build_nozzle_identifier

Build a canonical Bambu-style nozzle identifier.

decodeError

Decodes a raw print_error integer into a full HMS dictionary.

decodeHMS

Decodes the raw HMS list from telemetry into a structured list of dictionaries.

getAMSHeatingState

Decodes the AMS drying/heater state from bits 4-7 of the ams_info value.

getAMSModelBySerial

Returns the hardware model based on the serial number prefix.

getAMSSeriesByModel

Returns the AMS series enum based on the provided model.

getPrinterModelBySerial

Returns the Printer model enum based on the provided serial #.

getPrinterSeriesByModel

Returns the Printer series enum based on the provided model.

get_file_md5

Generates an MD5 hex hash for a given file.

jsonSerializer

Module-level JSON serializer for use with json.dumps(default=jsonSerializer).

nozzle_type_to_telemetry

Convert canonical NozzleType to telemetry/API string.

parseAMSInfo

Extracts all documented telemetry attributes from the AMS info hex string.

parseAMSStatus

Maps the ams_status code to human-readable descriptions.

parseExtruderInfo

Decodes the extruder 'info' bit-packed status using unique ExtruderInfoState names.

parseExtruderStatus

Decodes the operational extruder state using the exhaustive Enum map.

parseRFIDStatus

Can be used to parse ams_rfid_status

parseStage

Maps stg_cur numeric codes to human-readable print stages.

parse_nozzle_identifier

Parse a Bambu-style nozzle identifier into flow family, material, and diameter.

parse_nozzle_type

Resolve a nozzle type from cross-model telemetry strings or encoded IDs.

scaleFanSpeed

Scales proprietary 0-15 fan speed values to a 0-100 percentage.

sortFileTreeAlphabetically

Sorts a dict of file/directory nodes hierarchically.

unpackTemperature

Unpacks a 32-bit packed temperature integer into a tuple of (Actual, Target).

AMSControlCommand

Bases: Enum

AMS Control Commands enum

AMSDryFanStatus

Bases: IntEnum

AMS drying fan status extracted from bits 18-21 of ams_info. Two independent fans (fan1: bits 18-19, fan2: bits 20-21). Mapped from BambuStudio's DryFanStatus enum.

AMSDrySubStatus

Bases: IntEnum

AMS drying sub-status extracted from bits 22-25 of ams_info. Indicates the specific phase of the drying cycle. Mapped from BambuStudio's DrySubStatus enum.

AMSHeatingState

Bases: IntEnum

AMS Drying/Heater states extracted from bits 4-7 of ams_info. Mapped directly from BambuStudio's DryStatus enum. Only supported on AMS 2 Pro (N3F) and AMS HT (N3S) models.

AMSModel

Bases: IntEnum

AMS model enum

AMSSeries

Bases: Enum

AMS Series enum

AMSUserSetting

Bases: Enum

AMS User Settings enum

ActiveTool

Bases: IntEnum

The currently active extruder index.

  • SINGLE_EXTRUDER (-1): Standard single-toolhead architecture (X1/P1/A1).
  • RIGHT_EXTRUDER (0): The primary/right toolhead in H2D (Dual Extruder) systems.
  • LEFT_EXTRUDER (1): The secondary/left toolhead in H2D (Dual Extruder) systems.
  • NOT_ACTIVE (15): The multi-extruder system is in a transitional state.

AirConditioningMode

Bases: IntEnum

The mode the printer's air conditioning sub system is in.

  • NOT_SUPPORTED (-1): This printer is not equipped with this feature.
  • COOL_MODE (0): The printer is currently not heating. The top vent may be open if the exhaust fan is running.
  • HEAT_MODE (1): The printer is actively heating the chamber with the recirculation fan active.

DetectorSensitivity

Bases: Enum

Sensitivity level for X-Cam AI vision detectors (spaghetti, pile-up, clump, air-print). The string value is sent directly in the halt_print_sensitivity MQTT field.

ExtruderInfoState

Bases: IntEnum

Consolidated logical states for extruder sensor status. Values represent unique state IDs to prevent bitmask collisions.

ExtruderStatus

Bases: IntEnum

Operational states for physical extruders. Values are mapped directly from the Bambu Studio source code (BBL_EXTRUDER_STATE).

NozzleDiameter

Bases: Enum

Nozzle Diameter enum

NozzleFlowType

Bases: Enum

Canonical nozzle flow families used by BambuStudio/Orca nozzle identifiers.

Encoded as the second character in identifiers such as HS00-0.4.

NozzleMaterialCode

Bases: Enum

Canonical material codes used in encoded nozzle identifiers.

Encoded as characters 3-4 in identifiers such as HS00-0.4.

NozzleType

Bases: Enum

Canonical cross-model nozzle material type from telemetry.

This enum intentionally models only material/type categories that appear in telemetry and accessory APIs. Encoded variant identifiers such as HS01 are parsed via parse_nozzle_identifier() / parse_nozzle_type().

PlateType

Bases: Enum

Used by BambuPrinter.print_3mf_file to specify which plate should be used when starting a print job.

PrintOption

Bases: Enum

Print Option enum

PrinterModel

Bases: Enum

Printer model enum

PrinterSeries

Bases: Enum

Printer Series enum

ServiceState

Bases: Enum

This enum is used by bambu-printer-manager to track the underlying state of the mqtt connection to the printer.

TrayState

Bases: IntEnum

Operational status of the filament tray.

build_nozzle_identifier

Python
build_nozzle_identifier(
    flow_type: NozzleFlowType, nozzle_type: NozzleType, diameter: float | str
) -> str

Build a canonical Bambu-style nozzle identifier.

Examples

HS00-0.4, HH01-0.6, HU00-0.4

Source code in src/bpm/bambutools.py
Python
def build_nozzle_identifier(
    flow_type: NozzleFlowType, nozzle_type: NozzleType, diameter: float | str
) -> str:
    """
    Build a canonical Bambu-style nozzle identifier.

    Examples
    --------
    `HS00-0.4`, `HH01-0.6`, `HU00-0.4`
    """

    material = _TYPE_TO_MATERIAL_CODE.get(nozzle_type)
    if material is None:
        raise ValueError(f"Unsupported nozzle_type for encoded ID: {nozzle_type}")

    if flow_type not in {
        NozzleFlowType.STANDARD,
        NozzleFlowType.HIGH_FLOW,
        NozzleFlowType.TPU_HIGH_FLOW,
    }:
        raise ValueError(f"Unsupported flow_type for encoded ID: {flow_type}")

    if isinstance(diameter, float):
        diameter_str = f"{diameter:.1f}"
    else:
        diameter_str = str(diameter)

    return f"H{flow_type.value}{material.value}-{diameter_str}"

decodeError staticmethod

Python
decodeError(error: int) -> dict

Decodes a raw print_error integer into a full HMS dictionary.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def decodeError(error: int) -> dict:
    """
    Decodes a raw print_error integer into a full HMS dictionary.
    """
    if error == 0:
        return {}

    raw_hex = f"{error:08X}".upper()
    wiki_slug = "-".join(raw_hex[i : i + 4] for i in range(0, 8, 4))
    res = {
        "code": f"HMS_{wiki_slug}",
        "msg": "Unknown HMS Error",
        "module": "System",
        "severity": "Error",
        "is_critical": False,
        "type": "device_error",
        "url": f"https://e.bambulab.com/?e={raw_hex}",
    }

    real_module = (error >> 24) & 0xFF
    module_map = {
        0x03: "Mainboard",
        0x05: "AMS",
        0x12: "AMS",
        0x07: "Toolhead",
        0x0B: "Webcam",
        0x10: "HMS",
    }
    res["module"] = module_map.get(real_module, "System")

    msg_list = HMS_STATUS.get("data", {}).get("device_error", {}).get("en", [])
    modules = ["03", "05", "07", "0B", "0C", "10", "12"]
    if raw_hex[:2] in modules:
        modules.remove(raw_hex[:2])
    modules.insert(0, raw_hex[:2])

    for module in modules:
        current_hex = f"{module}{raw_hex[2:]}"
        for entry in msg_list:
            if entry.get("ecode", "").upper() == current_hex.upper():
                res["msg"] = entry.get("intro", res["msg"])
                break
        if res["msg"] != "Unknown HMS Error":
            break

    mask = (error >> 16) & 0xFF
    if mask in (0x00, 0x01):
        res["severity"] = "Fatal" if mask == 0x00 else "Error"
        res["is_critical"] = True
    elif mask == 0x02:
        res["severity"] = "Warning"
        res["is_critical"] = False
    else:
        res["severity"] = "Info"
        res["is_critical"] = False

    return res

decodeHMS staticmethod

Python
decodeHMS(hms_list: list) -> list[dict]

Decodes the raw HMS list from telemetry into a structured list of dictionaries.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def decodeHMS(hms_list: list) -> list[dict]:
    """
    Decodes the raw HMS list from telemetry into a structured list of dictionaries.
    """
    decoded_errors = []
    for item in hms_list:
        if isinstance(item, dict) and isinstance(item.get("code"), str):
            decoded_errors.append(item)
            continue
        try:
            attr = int(item.get("attr", 0))
            code = int(item.get("code", 0))
        except (AttributeError, ValueError, TypeError):
            continue
        if attr == 0:
            continue

        ecode = f"{attr:08X}{code:08X}"
        wiki_slug = "-".join(ecode[i : i + 4] for i in range(0, 16, 4))
        res = {
            "code": f"HMS_{wiki_slug}",
            "msg": "Unknown HMS Error",
            "module": "System",
            "severity": "Error",
            "is_critical": False,
            "type": "device_hms",
            "url": f"https://e.bambulab.com/?e={ecode}",
        }

        mid = (attr >> 24) & 0xFF
        mask = (attr >> 16) & 0xFF
        module_map = {
            0x03: "Mainboard",
            0x05: "AMS",
            0x12: "AMS",
            0x07: "Toolhead",
            0x0B: "Webcam",
            0x10: "HMS",
        }
        res["module"] = module_map.get(mid, "System")

        msg_list = HMS_STATUS.get("data", {}).get("device_hms", {}).get("en", [])
        for entry in msg_list:
            if entry.get("ecode", "").upper() == ecode:
                res["msg"] = entry.get("intro", res["msg"])
                break

        if mask in (0x00, 0x01):
            res["severity"], res["is_critical"] = (
                ("Fatal" if mask == 0x00 else "Error"),
                True,
            )
        elif mask == 0x02:
            res["severity"] = "Warning"
        else:
            res["severity"] = "Info"
        decoded_errors.append(res)
    return decoded_errors

getAMSHeatingState staticmethod

Python
getAMSHeatingState(ams_info: int) -> AMSHeatingState

Decodes the AMS drying/heater state from bits 4-7 of the ams_info value.

This implementation follows BambuStudio's DevFilaSystem parsing logic, extracting DryStatus from the info field.

Parameters:

Name Type Description Default

ams_info

int

Numeric AMS info value containing drying status in bits 4-7.

required

Returns:

Type Description
AMSHeatingState

AMSHeatingState enum representing the current drying/heater state.

AMSHeatingState

Only AMS 2 Pro (N3F) and AMS HT (N3S) support active drying states.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def getAMSHeatingState(ams_info: int) -> AMSHeatingState:
    """
    Decodes the AMS drying/heater state from bits 4-7 of the ams_info value.

    This implementation follows BambuStudio's DevFilaSystem parsing logic,
    extracting DryStatus from the info field.

    Args:
        ams_info: Numeric AMS info value containing drying status in bits 4-7.

    Returns:
        AMSHeatingState enum representing the current drying/heater state.
        Only AMS 2 Pro (N3F) and AMS HT (N3S) support active drying states.
    """
    # Extract DryStatus from bits 4-7 (right-shift by 4, mask 0x0F)
    dry_status = (ams_info >> 4) & 0x0F

    return AMSHeatingState(dry_status)

getAMSModelBySerial staticmethod

Python
getAMSModelBySerial(serial: str) -> AMSModel

Returns the hardware model based on the serial number prefix.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def getAMSModelBySerial(serial: str) -> AMSModel:
    """
    Returns the hardware model based on the serial number prefix.
    """
    prefix = serial[:3].upper()
    if prefix == "19C":
        return AMSModel.AMS_2_PRO
    if prefix == "19F":
        return AMSModel.AMS_HT
    if prefix == "006":
        return AMSModel.AMS_1
    if prefix == "03C":
        return AMSModel.AMS_LITE
    return AMSModel.UNKNOWN

getAMSSeriesByModel staticmethod

Python
getAMSSeriesByModel(model: AMSModel) -> AMSSeries

Returns the AMS series enum based on the provided model.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def getAMSSeriesByModel(model: AMSModel) -> AMSSeries:
    """
    Returns the AMS series enum based on the provided model.
    """
    if model in (AMSModel.AMS_1, AMSModel.AMS_LITE):
        return AMSSeries.GEN_1
    if model in (AMSModel.AMS_HT, AMSModel.AMS_2_PRO):
        return AMSSeries.GEN_2
    return AMSSeries.UNKNOWN

getPrinterModelBySerial staticmethod

Python
getPrinterModelBySerial(serial: str) -> PrinterModel

Returns the Printer model enum based on the provided serial #.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def getPrinterModelBySerial(serial: str) -> PrinterModel:
    """
    Returns the Printer model enum based on the provided serial #.
    """
    mapping = {
        "00M": PrinterModel.X1C,
        "00W": PrinterModel.X1,
        "03W": PrinterModel.X1E,
        "01S": PrinterModel.P1P,
        "01P": PrinterModel.P1S,
        "030": PrinterModel.A1_MINI,
        "039": PrinterModel.A1,
        "22E": PrinterModel.P2S,
        "093": PrinterModel.H2S,
        "094": PrinterModel.H2D,
    }
    prefix = serial[:3]
    return mapping.get(prefix, PrinterModel.UNKNOWN)

getPrinterSeriesByModel staticmethod

Python
getPrinterSeriesByModel(model: PrinterModel) -> PrinterSeries

Returns the Printer series enum based on the provided model.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def getPrinterSeriesByModel(model: PrinterModel) -> PrinterSeries:
    """
    Returns the Printer series enum based on the provided model.
    """
    try:
        return PrinterSeries[model.name[:2]]
    except (KeyError, AttributeError):
        return PrinterSeries.UNKNOWN

get_file_md5 staticmethod

Python
get_file_md5(file_path: str | Path) -> str

Generates an MD5 hex hash for a given file.

Parameters:

Name Type Description Default

file_path

str | Path

The path to the file (string or Path object).

required

Returns:

Type Description
str

The 32-character MD5 hexadecimal string.

Raises:

Type Description
FileNotFoundError

If the file does not exist.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def get_file_md5(file_path: str | Path) -> str:
    """
    Generates an MD5 hex hash for a given file.

    Args:
        file_path: The path to the file (string or Path object).

    Returns:
        The 32-character MD5 hexadecimal string.

    Raises:
        FileNotFoundError: If the file does not exist.
    """
    path = Path(file_path)

    if not path.is_file():
        raise FileNotFoundError(f"No file found at: {path}")

    md5_hash = hashlib.md5()

    with path.open("rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):
            md5_hash.update(chunk)

    return md5_hash.hexdigest().upper()

jsonSerializer

Python
jsonSerializer(obj: Any) -> Any

Module-level JSON serializer for use with json.dumps(default=jsonSerializer).

Handles dataclasses, objects with __dict__, and falls back to str(). Skips MQTT clients, threads, and mappingproxy instances that cannot be serialized meaningfully.

Source code in src/bpm/bambutools.py
Python
def jsonSerializer(obj: Any) -> Any:
    """
    Module-level JSON serializer for use with `json.dumps(default=jsonSerializer)`.

    Handles dataclasses, objects with `__dict__`, and falls back to `str()`.
    Skips MQTT clients, threads, and `mappingproxy` instances that cannot be
    serialized meaningfully.
    """
    try:
        if isinstance(obj, Thread):
            return ""
        if getattr(obj.__class__, "__module__", "").startswith("paho.mqtt"):
            return ""
        if str(obj.__class__).replace("<class '", "").replace("'>", "") == "mappingproxy":
            return ""
        return getattr(obj, "__dict__", str(obj))
    except Exception:
        return ""

nozzle_type_to_telemetry

Python
nozzle_type_to_telemetry(value: NozzleType) -> str

Convert canonical NozzleType to telemetry/API string.

Source code in src/bpm/bambutools.py
Python
def nozzle_type_to_telemetry(value: NozzleType) -> str:
    """
    Convert canonical `NozzleType` to telemetry/API string.
    """

    return _NOZZLE_TYPE_ENUM_TO_TELEMETRY.get(value, "unknown")

parseAMSInfo staticmethod

Python
parseAMSInfo(info_hex: str) -> dict

Extracts all documented telemetry attributes from the AMS info hex string.

Based on BambuStudio's DevFilaSystemParser::ParseAmsInfo implementation. Complete bit field mapping (32-bit integer): - Bits 0-3: AMS type (1=AMS, 2=AMS_LITE, 3=AMS_2_PRO/N3F, 4=AMS_HT/N3S) - Bits 4-7: Dry status (OFF/CHECKING/DRYING/COOLING/STOPPING/ERROR/etc) - Bits 8-11: Extruder ID (for H2D toolhead assignment) - Bits 18-19: Dry fan 1 status (OFF=0, ON=1) - Bits 20-21: Dry fan 2 status (OFF=0, ON=1) - Bits 22-25: Dry sub-status (OFF/HEATING/DEHUMIDIFY)

Parameters:

Name Type Description Default

info_hex

str

Hexadecimal string representation of AMS info value

required

Returns:

Type Description
dict

Dictionary with all extracted telemetry fields

Source code in src/bpm/bambutools.py
Python
@staticmethod
def parseAMSInfo(info_hex: str) -> dict:
    """
    Extracts all documented telemetry attributes from the AMS info hex string.

    Based on BambuStudio's DevFilaSystemParser::ParseAmsInfo implementation.
    Complete bit field mapping (32-bit integer):
    - Bits 0-3: AMS type (1=AMS, 2=AMS_LITE, 3=AMS_2_PRO/N3F, 4=AMS_HT/N3S)
    - Bits 4-7: Dry status (OFF/CHECKING/DRYING/COOLING/STOPPING/ERROR/etc)
    - Bits 8-11: Extruder ID (for H2D toolhead assignment)
    - Bits 18-19: Dry fan 1 status (OFF=0, ON=1)
    - Bits 20-21: Dry fan 2 status (OFF=0, ON=1)
    - Bits 22-25: Dry sub-status (OFF/HEATING/DEHUMIDIFY)

    Args:
        info_hex: Hexadecimal string representation of AMS info value

    Returns:
        Dictionary with all extracted telemetry fields
    """
    info = int(info_hex, 16)

    ams_type = info & 0x0F  # Bits 0-3
    dry_status = (info >> 4) & 0x0F  # Bits 4-7
    extruder_id = (info >> 8) & 0x0F  # Bits 8-11
    dry_fan1_status = (info >> 18) & 0x03  # Bits 18-19
    dry_fan2_status = (info >> 20) & 0x03  # Bits 20-21
    dry_sub_status = (info >> 22) & 0x0F  # Bits 22-25

    ret = {
        "ams_type": AMSModel(ams_type) if ams_type in range(5) else AMSModel.UNKNOWN,
        "heater_state": AMSHeatingState(dry_status),
        "extruder_id": extruder_id,
        "dry_fan1_status": AMSDryFanStatus(dry_fan1_status),
        "dry_fan2_status": AMSDryFanStatus(dry_fan2_status),
        "dry_sub_status": AMSDrySubStatus(dry_sub_status),
    }

    # print(f"\r\n{ret}\r\n")
    return ret

parseAMSStatus staticmethod

Python
parseAMSStatus(status_int: int) -> str

Maps the ams_status code to human-readable descriptions.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def parseAMSStatus(status_int: int) -> str:
    """
    Maps the ams_status code to human-readable descriptions.
    """
    main_status = (status_int >> 8) & 0xFF
    status_map = {
        0x00: "Idle",
        0x01: "Filament Changing",
        0x02: "RFID Identifying",
        0x03: "Assist/Engaged",
        0x04: "Calibration",
        0x10: "Self Check",
        0x20: "Debug",
        0xFF: "Unknown",
    }
    return status_map.get(main_status, "Idle")

parseExtruderInfo staticmethod

Python
parseExtruderInfo(info_int: int) -> ExtruderInfoState

Decodes the extruder 'info' bit-packed status using unique ExtruderInfoState names.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def parseExtruderInfo(info_int: int) -> ExtruderInfoState:
    """
    Decodes the extruder 'info' bit-packed status using unique ExtruderInfoState names.
    """
    if not (info_int & 0x08):
        return ExtruderInfoState.NO_NOZZLE
    if info_int & 0x02:
        return ExtruderInfoState.LOADED
    if info_int & 0x04:
        return ExtruderInfoState.BUFFER_LOADED
    return ExtruderInfoState.EMPTY

parseExtruderStatus staticmethod

Python
parseExtruderStatus(stat_int: int) -> ExtruderStatus

Decodes the operational extruder state using the exhaustive Enum map.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def parseExtruderStatus(stat_int: int) -> ExtruderStatus:
    """
    Decodes the operational extruder state using the exhaustive Enum map.
    """
    working_bits = (stat_int >> 8) & 0x03
    if working_bits in (0x02, 0x03):
        return ExtruderStatus.ACTIVE
    if stat_int & 0x01:
        return ExtruderStatus.HEATING
    return ExtruderStatus.IDLE

parseRFIDStatus staticmethod

Python
parseRFIDStatus(status)

Can be used to parse ams_rfid_status

Source code in src/bpm/bambutools.py
Python
@staticmethod
def parseRFIDStatus(status):
    """
    Can be used to parse `ams_rfid_status`
    """
    rfid_map = {
        0: "RFID Idle",
        1: "RFID Reading",
        2: "GCode Translating",
        3: "GCode Running",
        4: "RFID Assistant",
        5: "Switch Filament",
        6: "Has Filament",
    }
    return rfid_map.get(status, "Unknown")

parseStage staticmethod

Python
parseStage(stage_int: int) -> str

Maps stg_cur numeric codes to human-readable print stages.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def parseStage(stage_int: int) -> str:
    """
    Maps stg_cur numeric codes to human-readable print stages.
    """
    stage_map = {
        -1: "",
        0: "",
        1: "Auto bed leveling",
        2: "Heatbed preheating",
        3: "Sweeping XY mech mode",
        4: "Changing filament",
        5: "M400 pause",
        6: "Filament runout pause",
        7: "Heating hotend",
        8: "Calibrating extrusion",
        9: "Scanning bed surface",
        10: "Inspecting first layer",
        11: "Identifying build plate",
        12: "Calibrating Micro Lidar",
        13: "Homing toolhead",
        14: "Cleaning nozzle tip",
        15: "Temp check",
        16: "Paused by user",
        17: "Front cover falling",
        18: "Lidar calibration (alt)",
        19: "Calibrating flow",
        20: "Nozzle temp malfunction",
        21: "Bed temp malfunction",
        22: "Filament unloading",
        23: "Skip step pause",
        24: "Filament loading",
        25: "Motor noise calibration",
        26: "AMS lost pause",
        27: "Fan speed pause",
        28: "Chamber control error",
        29: "Cooling chamber",
        30: "Custom Gcode pause",
        31: "Motor noise showoff",
        32: "Nozzle cover pause",
        33: "Cutter error pause",
        34: "First layer error pause",
        35: "Nozzle clog pause",
        36: "Absolute accuracy pre-check",
        37: "Chamber control",
        38: "Absolute accuracy post-check",
        39: "Nozzle Offset Calibration",
        40: "Bed level high temperature",
        41: "Check quick release",
        42: "Check door and cover",
        43: "Laser calibration",
        44: "Check platform",
        45: "Check birdeye camera position",
        46: "Calibrate birdeye camera",
        47: "Bed level phase 1",
        48: "Bed level phase 2",
        49: "Heating chamber",
        50: "Heated bed cooling",
        51: "Print calibration lines",
        52: "Check material",
        53: "Calibrating live view camera",
        54: "Waiting for heatbed temperature",
        55: "Check material position",
        56: "Calibrating cutter model offset",
        57: "Measuring surface",
        58: "Thermal preconditioning",
        70: "Leading filament",
        71: "Reached toolhead",
        72: "Grabbing filament",
        73: "Purging",
        74: "Homing toolhead",
        75: "Returning to AMS",
        76: "Cutting",
        77: "Tool switching",
        100: "Printing",
        255: "Completed",
    }
    return stage_map.get(stage_int, f"Stage [{stage_int}]")

parse_nozzle_identifier

Python
parse_nozzle_identifier(nozzle_id: str) -> tuple[NozzleFlowType, NozzleType, str]

Parse a Bambu-style nozzle identifier into flow family, material, and diameter.

Supported encoded formats include values such as HS00-0.4, HH01-0.6, and HU00-0.4.

Returns

tuple[NozzleFlowType, NozzleType, str] A tuple of (flow_type, nozzle_type, diameter). Unknown/unsupported parts are returned as UNKNOWN enum values.

Source code in src/bpm/bambutools.py
Python
def parse_nozzle_identifier(nozzle_id: str) -> tuple[NozzleFlowType, NozzleType, str]:
    """
    Parse a Bambu-style nozzle identifier into flow family, material, and diameter.

    Supported encoded formats include values such as `HS00-0.4`, `HH01-0.6`,
    and `HU00-0.4`.

    Returns
    -------
    tuple[NozzleFlowType, NozzleType, str]
        A tuple of `(flow_type, nozzle_type, diameter)`.
        Unknown/unsupported parts are returned as `UNKNOWN` enum values.
    """

    if not nozzle_id:
        return (NozzleFlowType.UNKNOWN, NozzleType.UNKNOWN, "")

    clean = nozzle_id.strip()
    if "-" in clean:
        encoded, diameter = clean.split("-", 1)
    else:
        encoded, diameter = clean, ""

    if len(encoded) < 4:
        return (NozzleFlowType.UNKNOWN, NozzleType.UNKNOWN, diameter)

    flow = _FLOW_CODE_TO_TYPE.get(encoded[1], NozzleFlowType.UNKNOWN)
    material_code = encoded[2:4]
    nozzle_type = _MATERIAL_CODE_TO_TYPE.get(material_code, NozzleType.UNKNOWN)

    return (flow, nozzle_type, diameter)

parse_nozzle_type

Python
parse_nozzle_type(value: str | None) -> NozzleType

Resolve a nozzle type from cross-model telemetry strings or encoded IDs.

Supports direct telemetry values (for example hardened_steel) and encoded forms (for example HH01-0.4, HS00, HU05).

Source code in src/bpm/bambutools.py
Python
def parse_nozzle_type(value: str | None) -> NozzleType:
    """
    Resolve a nozzle type from cross-model telemetry strings or encoded IDs.

    Supports direct telemetry values (for example `hardened_steel`) and encoded
    forms (for example `HH01-0.4`, `HS00`, `HU05`).
    """

    if value is None:
        return NozzleType.UNKNOWN

    clean = value.strip()
    if not clean:
        return NozzleType.UNKNOWN

    telemetry_key = clean.lower()
    if telemetry_key in _NOZZLE_TYPE_TELEMETRY_TO_ENUM:
        return _NOZZLE_TYPE_TELEMETRY_TO_ENUM[telemetry_key]

    if clean in _MATERIAL_CODE_TO_TYPE:
        return _MATERIAL_CODE_TO_TYPE[clean]

    _, nozzle_type, _ = parse_nozzle_identifier(clean)
    if nozzle_type != NozzleType.UNKNOWN:
        return nozzle_type

    try:
        return NozzleType[clean.upper()]
    except (KeyError, ValueError):
        return NozzleType.UNKNOWN

scaleFanSpeed staticmethod

Python
scaleFanSpeed(raw_val: Any) -> int

Scales proprietary 0-15 fan speed values to a 0-100 percentage.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def scaleFanSpeed(raw_val: Any) -> int:
    """
    Scales proprietary 0-15 fan speed values to a 0-100 percentage.
    """
    try:
        val = int(raw_val)
        return min(max(round((val / 15.0) * 100), 0), 100)
    except Exception:
        return 0

sortFileTreeAlphabetically staticmethod

Python
sortFileTreeAlphabetically(source) -> dict

Sorts a dict of file/directory nodes hierarchically.

Source code in src/bpm/bambutools.py
Python
@staticmethod
def sortFileTreeAlphabetically(source) -> dict:
    """
    Sorts a dict of file/directory nodes hierarchically.
    """

    def sort_node_list(node_list):
        for item in node_list:
            if item.get("id", "").endswith("/") and "children" in item:
                item["children"] = sort_node_list(item["children"])
        return sorted(
            node_list,
            key=lambda i: (not i.get("id", "").endswith("/"), i.get("name", "").lower()),
        )

    source["children"] = sort_node_list(source["children"])
    return source

unpackTemperature staticmethod

Python
unpackTemperature(raw_temp: int) -> tuple[float, float]

Unpacks a 32-bit packed temperature integer into a tuple of (Actual, Target).

Source code in src/bpm/bambutools.py
Python
@staticmethod
def unpackTemperature(raw_temp: int) -> tuple[float, float]:
    """
    Unpacks a 32-bit packed temperature integer into a tuple of (Actual, Target).
    """
    return float(raw_temp & 0xFFFF), float((raw_temp >> 16) & 0xFFFF)