Skip to content

bambudiscovery

Hosts the discovery service which provides a wrapper for reading and parsing the Bambu Lab Discovery (SSDP) protocol.

Classes:

Name Description
BambuDiscovery

Manages the SSDP discovery thread for Bambu Lab printers.

DiscoveredPrinter

Represents a parsed SSDP response from a Bambu Lab printer.

BambuDiscovery

Python
BambuDiscovery(
    on_printer_discovered=None, on_discovery_ended=None, discovery_timeout: int = 15
)

Manages the SSDP discovery thread for Bambu Lab printers.

Methods:

Name Description
start

Start the discovery thread.

stop

Stop the discovery thread.

Attributes:

Name Type Description
discovered_printers

Get the dict of discovered printers keyed by USN.

running

Check if discovery is currently running.

Source code in src/bpm/bambudiscovery.py
Python
def __init__(
    self,
    on_printer_discovered=None,
    on_discovery_ended=None,
    discovery_timeout: int = 15,
):
    self.discovery_timeout = discovery_timeout
    self._thread = None
    self._timer = None
    self._running = False
    self._discovered_printers = {}
    self._on_printer_discovered = on_printer_discovered
    self._on_discovery_ended = on_discovery_ended

discovered_printers property

Python
discovered_printers

Get the dict of discovered printers keyed by USN.

running property

Python
running

Check if discovery is currently running.

start

Python
start()

Start the discovery thread.

Source code in src/bpm/bambudiscovery.py
Python
def start(self):
    """Start the discovery thread."""
    if self._thread is None or not self._thread.is_alive():
        self._running = True
        self._thread = threading.Thread(
            target=self._discovery_thread, name="bpm-discovery-thread"
        )
        self._thread.start()
        self._timer = threading.Timer(self.discovery_timeout, self._stop_on_timeout)
        self._timer.start()

stop

Python
stop()

Stop the discovery thread.

Source code in src/bpm/bambudiscovery.py
Python
def stop(self):
    """Stop the discovery thread."""
    self._running = False
    if self._timer:
        self._timer.cancel()
    if self._thread:
        self._thread.join()
    if self._on_discovery_ended:
        self._on_discovery_ended(self._discovered_printers)

DiscoveredPrinter dataclass

Python
DiscoveredPrinter(
    usn: str,
    host: str = "",
    server: str = "",
    location: str = "",
    nt: str = "",
    nts: str = "",
    cache_control: str = "",
    dev_model: str = "",
    decoded_model: PrinterModel = UNKNOWN,
    dev_name: str = "",
    dev_connect: str = "",
    dev_bind: str = "",
    dev_seclink: str = "",
    dev_inf: str = "",
    dev_version: str = "",
    dev_cap: str = "",
)

Represents a parsed SSDP response from a Bambu Lab printer.

Methods:

Name Description
fromData

Parse SSDP data string into a DiscoveredPrinter instance.

Attributes:

Name Type Description
cache_control str

The cache control header with max-age (e.g., max-age=1800).

decoded_model PrinterModel

The decoded printer model enum (e.g., PrinterModel.O1D).

dev_bind str

The binding status (e.g., free).

dev_cap str

The device capabilities flag (e.g., 1).

dev_connect str

The connection type (e.g., lan).

dev_inf str

The network interface (e.g., wlan0).

dev_model str

The printer model (e.g., O1D).

dev_name str

The printer name (e.g., 3DP-094-913).

dev_seclink str

The security link status (e.g., secure).

dev_version str

The device firmware version (e.g., 01.02.00.00).

host str

The SSDP multicast address and port (e.g., 239.255.255.250:1990).

location str

The IP address of the printer.

nt str

The notification type (e.g., urn:bambulab-com:device:3dprinter:1).

nts str

The notification subtype (e.g., ssdp:alive).

server str

The UPnP server identifier (e.g., UPnP/1.0).

usn str

The unique service name, typically the printer serial number.

cache_control class-attribute instance-attribute

Python
cache_control: str = ''

The cache control header with max-age (e.g., max-age=1800).

decoded_model class-attribute instance-attribute

Python
decoded_model: PrinterModel = UNKNOWN

The decoded printer model enum (e.g., PrinterModel.O1D).

dev_bind class-attribute instance-attribute

Python
dev_bind: str = ''

The binding status (e.g., free).

dev_cap class-attribute instance-attribute

Python
dev_cap: str = ''

The device capabilities flag (e.g., 1).

dev_connect class-attribute instance-attribute

Python
dev_connect: str = ''

The connection type (e.g., lan).

dev_inf class-attribute instance-attribute

Python
dev_inf: str = ''

The network interface (e.g., wlan0).

dev_model class-attribute instance-attribute

Python
dev_model: str = ''

The printer model (e.g., O1D).

dev_name class-attribute instance-attribute

Python
dev_name: str = ''

The printer name (e.g., 3DP-094-913).

Python
dev_seclink: str = ''

The security link status (e.g., secure).

dev_version class-attribute instance-attribute

Python
dev_version: str = ''

The device firmware version (e.g., 01.02.00.00).

host class-attribute instance-attribute

Python
host: str = ''

The SSDP multicast address and port (e.g., 239.255.255.250:1990).

location class-attribute instance-attribute

Python
location: str = ''

The IP address of the printer.

nt class-attribute instance-attribute

Python
nt: str = ''

The notification type (e.g., urn:bambulab-com:device:3dprinter:1).

nts class-attribute instance-attribute

Python
nts: str = ''

The notification subtype (e.g., ssdp:alive).

server class-attribute instance-attribute

Python
server: str = ''

The UPnP server identifier (e.g., UPnP/1.0).

usn instance-attribute

Python
usn: str

The unique service name, typically the printer serial number.

fromData classmethod

Python
fromData(data: str) -> DiscoveredPrinter

Parse SSDP data string into a DiscoveredPrinter instance.

Source code in src/bpm/bambudiscovery.py
Python
@classmethod
def fromData(cls, data: str) -> "DiscoveredPrinter":
    """Parse SSDP data string into a  DiscoveredPrinter instance."""
    lines = data.strip().split("\n")
    parsed = {}
    for line in lines:
        if ":" in line:
            key, value = line.split(":", 1)
            key = key.strip().lower()
            value = value.strip()
            if key == "host":
                parsed["host"] = value
            elif key == "server":
                parsed["server"] = value
            elif key == "location":
                parsed["location"] = value
            elif key == "nt":
                parsed["nt"] = value
            elif key == "nts":
                parsed["nts"] = value
            elif key == "usn":
                parsed["usn"] = value
                parsed["decoded_model"] = getPrinterModelBySerial(value)
            elif key == "cache-control":
                parsed["cache_control"] = value
            elif key == "devmodel.bambu.com":
                parsed["dev_model"] = value
            elif key == "devname.bambu.com":
                parsed["dev_name"] = value
            elif key == "devconnect.bambu.com":
                parsed["dev_connect"] = value
            elif key == "devbind.bambu.com":
                parsed["dev_bind"] = value
            elif key == "devseclink.bambu.com":
                parsed["dev_seclink"] = value
            elif key == "devinf.bambu.com":
                parsed["dev_inf"] = value
            elif key == "devversion.bambu.com":
                parsed["dev_version"] = value
            elif key == "devcap.bambu.com":
                parsed["dev_cap"] = value
    return cls(**parsed)