bambulan

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2025 License: MIT Imports: 13 Imported by: 0

README

BambuLAN Logo

BambuLAN

A Go library for interacting with Bambu Lab 3D printers over the local network (LAN mode).

This library allows you to monitor printer status, control print jobs, view the camera stream, and manage files without relying on the Bambu Lab cloud service.

Features

  • LAN Control: Connects directly to the printer's MQTT broker (port 8883).
  • Status Monitoring: Receive real-time updates on temperatures, fans, print progress, and more.
  • Commands:
    • Control prints (print start <file>, print pause, print resume, print stop).
    • Set print speed profiles (silent, standard, sport, ludicrous).
    • Control chamber lights.
    • Send raw G-Code (single line).
  • Camera Streaming: Connect to the printer's camera stream (MJPEG over TCP/TLS port 6000).
  • File Management: List and download files (timelapses, models) via FTPS (port 990).
  • Web Interface: A built-in web dashboard to monitor and control the printer.

Installation

go get github.com/gonzalop/bambulan

Usage

Connecting and Monitoring
package main

import (
    "fmt"
    "log"
    "github.com/gonzalop/bambulan"
)

func main() {
    // 1. Define configuration
    host := "192.168.1.50"
    accessCode := "12345678" // Found in printer settings
    serial := "01S00A..."

    // 2. Define a callback for status updates
    onUpdate := func(status *bambulan.PrinterStatus) {
        fmt.Printf("Nozzle: %.1f°C | Bed: %.1f°C | Progress: %d%%\n",
            status.NozzleTemper, status.BedTemper, status.McPercent)
    }

    // 3. Initialize and Start Client
    client := bambulan.NewClient(host, accessCode, serial, onUpdate)

    if err := client.Start(); err != nil {
        log.Fatalf("Failed to connect: %v", err)
    }
    defer client.Stop()

    // Keep running...
    select {}
}
Sending Commands
// Turn light on
client.MQTT.SetChamberLight(true)

// set speed to "Sport"
client.MQTT.SetSpeedProfile("3")

// Pause print
client.MQTT.PausePrint()
Camera Capture
// Capture a single JPEG frame
imgData, err := client.Camera.CaptureFrame()
if err != nil {
    log.Println("Error capturing frame:", err)
}
// imgData contains the JPEG bytes
File Management
// List .3mf files
files, err := client.File.GetFiles("/", ".3mf")
if err != nil {
    log.Println("Error listing files:", err)
}

// Download a file
err := client.File.DownloadFile("/timelapse/video.mp4", "./video.mp4")

CLI Tool / Web Interface

The included cmd/bambulan builds into a powerful CLI tool named bambulan, which also includes a web interface.

BambuLAN Dashboard

See cmd/bambulan/README.md for full usage instructions.

Build
go build -o bambulan ./cmd/bambulan

Development

Prerequisites
  • Go 1.25+
  • make
Available Commands
  • Default: Formatting, linting, and building.
    make
    
  • Build: Compile the project.
    make build
    
  • Test: Run unit tests.
    make test
    
  • Lint: Run golangci-lint to check for specific linter errors.
    make golangci-lint-run
    
  • Format: Format code using goimports.
    make fmt
    
  • Cross-compile: Build binaries for Linux, macOS, and Windows.
    make build-all
    
  • Clean: Remove build artifacts.
    make clean
    

Acknowledgements

This project builds upon the hard work of the community in reverse-engineering the Bambu Lab network protocol. Special thanks to:

Disclaimer

This library is not affiliated with or endorsed by Bambu Lab. Use it at your own risk. Protocol details were reverse-engineered from open-source community efforts.

Documentation

Overview

Package bambulan provides a client library for interacting with Bambu Lab 3D printers over the local area network (LAN).

It supports: - MQTT for status monitoring and command control (printing, lights, speed). - FTPS for file management (listing, uploading, downloading). - Camera access for frame capture.

Example usage:

client := bambulan.NewClient("192.168.1.100", "access_code", "serial_number", func(status *bambulan.PrinterStatus) {
	fmt.Printf("Progress: %d%%\n", status.McPercent)
})

if err := client.Start(); err != nil {
	log.Fatal(err)
}
defer client.Stop()

// ... interaction ...

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AMS

type AMS struct {
	Ams              []*AMSEntry `json:"ams"`
	AmsExistBits     string      `json:"ams_exist_bits"`
	AmsExistBitsRaw  string      `json:"ams_exist_bits_raw"`
	TrayExistBits    string      `json:"tray_exist_bits"`
	TrayIsBblBits    string      `json:"tray_is_bbl_bits"`
	TrayTar          string      `json:"tray_tar"`
	TrayNow          string      `json:"tray_now"`
	TrayPre          string      `json:"tray_pre"`
	TrayReadDoneBits string      `json:"tray_read_done_bits"`
	TrayReadingBits  string      `json:"tray_reading_bits"`
	Version          int         `json:"version"`
	InsertFlag       bool        `json:"insert_flag"`
	PowerOnFlag      bool        `json:"power_on_flag"`
}

type AMSEntry

type AMSEntry struct {
	Humidity string    `json:"humidity"`
	Id       string    `json:"id"`
	Temp     string    `json:"temp"`
	Tray     []*VTTray `json:"tray"`
}

type CameraClient

type CameraClient struct {
	Hostname   string
	AccessCode string
	Port       int
	Username   string
	// contains filtered or unexported fields
}

CameraClient handles the MJPEG camera stream connection over TCP/TLS.

func NewCameraClient

func NewCameraClient(hostname, accessCode string) *CameraClient

NewCameraClient creates a new CameraClient.

func (*CameraClient) CaptureFrame

func (c *CameraClient) CaptureFrame() ([]byte, error)

CaptureFrame connects to the camera, captures a single frame, and closes the connection. It returns the JPEG byte slice or an error.

func (*CameraClient) StartStream

func (c *CameraClient) StartStream(onImage func([]byte)) error

StartStream connects to the camera and continuously sends new JPEG frames to the onImage callback.

func (*CameraClient) StopStream

func (c *CameraClient) StopStream()

StopStream stops the camera stream if it is running.

type Client

type Client struct {
	MQTT   *MQTTClient
	Camera *CameraClient
	File   *FileClient
	// OnUpdate is a callback for status updates. It delegates to MQTT.OnUpdate.
	OnUpdate func(*PrinterStatus)
}

Client is the main entry point for the BambuLAN library. It coordinates MQTT, Camera, and File clients.

func NewClient

func NewClient(hostname, accessCode, serial string, onUpdate func(*PrinterStatus)) *Client

NewClient creates a new BambuLAN Client. It requires the printer's hostname (IP), access code (from settings), and serial number. The onUpdate callback is invoked whenever a status update is received from the printer.

func (*Client) GetPrinterStatus

func (c *Client) GetPrinterStatus() *PrinterStatus

GetPrinterStatus returns the underlying printer status.

func (*Client) Start

func (c *Client) Start() error

Start initiates the MQTT connection and starts listening for status updates. It returns an error if the connection fails.

func (*Client) Stop

func (c *Client) Stop()

Stop gracefully shuts down the MQTT connection and any active camera streams.

type FileClient

type FileClient struct {
	Hostname   string
	AccessCode string
}

FileClient handles file operations (listing, uploading, downloading) over FTPS.

func NewFileClient

func NewFileClient(hostname, accessCode string) *FileClient

NewFileClient creates a new FileClient.

func (*FileClient) Download

func (f *FileClient) Download(remotePath string) (io.ReadCloser, error)

Download streams a file from the printer. The caller is responsible for closing the returned ReadCloser.

func (*FileClient) DownloadFile

func (f *FileClient) DownloadFile(remotePath, localPath string, onProgress func(int64, int64)) error

DownloadFile downloads a file from the printer to a local path. The onProgress callback, if not nil, reports the current downloaded bytes and total size.

func (*FileClient) GetFiles

func (f *FileClient) GetFiles(dir string, extension string) ([]string, error)

GetFiles returns a list of files in the specified directory with the given extension.

func (*FileClient) ListFiles

func (f *FileClient) ListFiles(dir string) ([]*ftp.Entry, error)

ListFiles returns a detailed list of files in the specified directory.

func (*FileClient) Upload

func (f *FileClient) Upload(remotePath string, content io.Reader) error

Upload streams content to the printer.

func (*FileClient) UploadFile

func (f *FileClient) UploadFile(localPath, remotePath string, onProgress func(int64, int64)) error

UploadFile uploads a local file to the printer. The onProgress callback, if not nil, reports the current uploaded bytes and total size.

type IPCam

type IPCam struct {
	AgoraService string `json:"agora_service"`
	IpcamDev     string `json:"ipcam_dev"`
	IpcamRecord  string `json:"ipcam_record"`
	Timelapse    string `json:"timelapse"`
	Resolution   string `json:"resolution"`
	TutkServer   string `json:"tutk_server"`
	ModeBits     int    `json:"mode_bits"`
	RtspUrl      string `json:"rtsp_url"`
}

type LightsReport

type LightsReport struct {
	Node string `json:"node"`
	Mode string `json:"mode"`
}

type MQTTClient

type MQTTClient struct {
	Hostname   string
	AccessCode string
	Serial     string

	OnUpdate func(*PrinterStatus)
	// contains filtered or unexported fields
}

MQTTClient handles the MQTT connection to the printer.

func NewMQTTClient

func NewMQTTClient(hostname, accessCode, serial string, onUpdate func(*PrinterStatus)) *MQTTClient

NewMQTTClient creates a new MQTTClient.

func (*MQTTClient) DumpInfo

func (m *MQTTClient) DumpInfo() error

DumpInfo requests a full status push from the printer.

func (*MQTTClient) GetPrinterStatus

func (m *MQTTClient) GetPrinterStatus() *PrinterStatus

GetPrinterStatus returns the current status pointer.

func (*MQTTClient) PausePrint

func (m *MQTTClient) PausePrint() error

PausePrint pauses the current print job.

func (*MQTTClient) Publish

func (m *MQTTClient) Publish(command interface{}) error

Publish sends a JSON command to the printer request topic.

func (*MQTTClient) ResumePrint

func (m *MQTTClient) ResumePrint() error

ResumePrint resumes a paused print job.

func (*MQTTClient) SendGCode

func (m *MQTTClient) SendGCode(gcode string) error

SendGCode sends a single line of G-Code to the printer.

func (*MQTTClient) SetChamberLight

func (m *MQTTClient) SetChamberLight(on bool) error

SetChamberLight turns the chamber light on or off.

func (*MQTTClient) SetSpeedProfile

func (m *MQTTClient) SetSpeedProfile(level string) error

SetSpeedProfile sets the print speed profile. Supported levels are: 1=Silent, 2=Standard, 3=Sport, 4=Ludicrous.

func (*MQTTClient) Start

func (m *MQTTClient) Start() error

Start connects to the MQTT broker and subscribes to report topics.

func (*MQTTClient) StartPrint

func (m *MQTTClient) StartPrint(filename string, opts PrintOptions) error

StartPrint starts a print job for a file already on the printer (SD card). The filename specifies the path to the file on the printer (e.g., "Metadata/plate_1.gcode" or "model.gcode").

func (*MQTTClient) Stop

func (m *MQTTClient) Stop()

Stop disconnects from the MQTT broker.

func (*MQTTClient) StopPrint

func (m *MQTTClient) StopPrint() error

StopPrint cancels and stops the current print job.

type Message

type Message struct {
	Print *PrinterStatus `json:"print"`
}

Message represents the top-level JSON structure received from the printer.

type Online

type Online struct {
	Ahb     bool `json:"ahb"`
	Ext     bool `json:"ext"`
	Rfid    bool `json:"rfid"`
	Version int  `json:"version"`
}

type PrintOptions

type PrintOptions struct {
	BedType              string
	Timelapse            bool
	BedLeveling          bool
	FlowCalibration      bool
	VibrationCalibration bool
	LayerInspection      bool
	UseAMS               bool
}

PrintOptions configures the parameters for starting a print job.

type PrinterStatus

type PrinterStatus struct {
	Upload                  *Upload         `json:"upload,omitempty"`
	NozzleTemp              float64         `json:"nozzle_temper"`
	NozzleTargetTemp        float64         `json:"nozzle_target_temper"`
	BedTemp                 float64         `json:"bed_temper"`
	BedTargetTemp           float64         `json:"bed_target_temper"`
	ChamberTemp             float64         `json:"chamber_temper"`
	McPrintStage            string          `json:"mc_print_stage"`
	HeatbreakFanSpeed       string          `json:"heatbreak_fan_speed"`
	CoolingFanSpeed         string          `json:"cooling_fan_speed"`
	BigFan1Speed            string          `json:"big_fan1_speed"`
	BigFan2Speed            string          `json:"big_fan2_speed"`
	McPercent               int             `json:"mc_percent"`
	McRemainingTime         int             `json:"mc_remaining_time"`
	AmsStatus               int             `json:"ams_status"`
	AmsRfidStatus           int             `json:"ams_rfid_status"`
	HwSwitchState           int             `json:"hw_switch_state"`
	SpdMag                  int             `json:"spd_mag"`
	SpdLvl                  int             `json:"spd_lvl"`
	PrintError              int             `json:"print_error"`
	Lifecycle               string          `json:"lifecycle"`
	WifiSignal              string          `json:"wifi_signal"`
	GcodeState              string          `json:"gcode_state"`
	GcodeFilePreparePercent string          `json:"gcode_file_prepare_percent"`
	QueueNumber             int             `json:"queue_number"`
	QueueTotal              int             `json:"queue_total"`
	QueueEst                int             `json:"queue_est"`
	QueueSts                int             `json:"queue_sts"`
	ProjectId               string          `json:"project_id"`
	ProfileId               string          `json:"profile_id"`
	TaskId                  string          `json:"task_id"`
	SubtaskId               string          `json:"subtask_id"`
	SubtaskName             string          `json:"subtask_name"`
	GcodeFile               string          `json:"gcode_file"`
	Stg                     []interface{}   `json:"stg"`
	StgCur                  int             `json:"stg_cur"`
	PrintType               string          `json:"print_type"`
	HomeFlag                int             `json:"home_flag"`
	McPrintLineNumber       string          `json:"mc_print_line_number"`
	McPrintSubStage         int             `json:"mc_print_sub_stage"`
	Sdcard                  bool            `json:"sdcard"`
	ForceUpgrade            bool            `json:"force_upgrade"`
	MessProductionState     string          `json:"mess_production_state"`
	LayerNum                int             `json:"layer_num"`
	TotalLayerNum           int             `json:"total_layer_num"`
	SObj                    []interface{}   `json:"s_obj"`
	FanGear                 int             `json:"fan_gear"`
	Hms                     []interface{}   `json:"hms"`
	Online                  *Online         `json:"online,omitempty"`
	Ams                     *AMS            `json:"ams,omitempty"`
	Ipcam                   *IPCam          `json:"ipcam,omitempty"`
	VtTray                  *VTTray         `json:"vt_tray,omitempty"`
	LightsReport            []*LightsReport `json:"lights_report,omitempty"`
	UpgradeState            *UpgradeState   `json:"upgrade_state,omitempty"`
	Command                 string          `json:"command"`
	Msg                     int             `json:"msg"`
	SequenceId              string          `json:"sequence_id"`
}

PrinterStatus contains the detailed status of the printer components.

func (*PrinterStatus) GetPrintStageName

func (p *PrinterStatus) GetPrintStageName() string

GetPrintStageName converts the numeric print stage code into a human-readable string.

type UpgradeState

type UpgradeState struct {
	SequenceId          int           `json:"sequence_id"`
	Progress            string        `json:"progress"`
	Status              string        `json:"status"`
	ConsistencyRequest  bool          `json:"consistency_request"`
	DisState            int           `json:"dis_state"`
	ErrCode             int           `json:"err_code"`
	ForceUpgrade        bool          `json:"force_upgrade"`
	Message             string        `json:"message"`
	Module              string        `json:"module"`
	NewVersionState     int           `json:"new_version_state"`
	NewVerList          []interface{} `json:"new_ver_list"`
	CurStateCode        int           `json:"cur_state_code"`
	AhbNewVersionNumber string        `json:"ahb_new_version_number"`
	AmsNewVersionNumber string        `json:"ams_new_version_number"`
	ExtNewVersionNumber string        `json:"ext_new_version_number"`
	Idx                 int           `json:"idx"`
	Idx1                int           `json:"idx1"`
	LowerLimit          string        `json:"lower_limit"`
	OtaNewVersionNumber string        `json:"ota_new_version_number"`
	Sn                  string        `json:"sn"`
}

type Upload

type Upload struct {
	FileSize      int    `json:"file_size"`
	FinishSize    int    `json:"finish_size"`
	Status        string `json:"status"`
	Progress      int    `json:"progress"`
	Message       string `json:"message"`
	OssUrl        string `json:"oss_url"`
	SequenceId    string `json:"sequence_id"`
	Speed         int    `json:"speed"`
	TaskId        string `json:"task_id"`
	TimeRemaining int    `json:"time_remaining"`
	TroubleId     string `json:"trouble_id"`
}

type VTTray

type VTTray struct {
	Id            string   `json:"id"`
	TagUid        string   `json:"tag_uid"`
	TrayIdName    string   `json:"tray_id_name"`
	TrayInfoIdx   string   `json:"tray_info_idx"`
	TrayType      string   `json:"tray_type"`
	TraySubBrands string   `json:"tray_sub_brands"`
	TrayColor     string   `json:"tray_color"`
	TrayWeight    string   `json:"tray_weight"`
	TrayDiameter  string   `json:"tray_diameter"`
	TrayTemp      string   `json:"tray_temp"`
	TrayTime      string   `json:"tray_time"`
	BedTempType   string   `json:"bed_temp_type"`
	BedTemp       string   `json:"bed_temp"`
	NozzleTempMax string   `json:"nozzle_temp_max"`
	NozzleTempMin string   `json:"nozzle_temp_min"`
	XcamInfo      string   `json:"xcam_info"`
	TrayUuid      string   `json:"tray_uuid"`
	Remain        int      `json:"remain"`
	K             float64  `json:"k"`
	N             int      `json:"n"`
	CaliIdx       int      `json:"cali_idx"`
	Cols          []string `json:"cols"`
	Ctype         int      `json:"ctype"`
	DryingTemp    string   `json:"drying_temp"`
	DryingTime    string   `json:"drying_time"`
}

Directories

Path Synopsis
cmd
bambulan command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL