@hiv3d/bambu-node
Version:
A node.js library for connecting to and receiving data from Bambu Lab printers through their MQTT servers.
1,586 lines (1,555 loc) • 63.5 kB
TypeScript
import * as mqtt from 'mqtt';
import { MqttClient } from 'mqtt';
import * as events from 'eventemitter3';
type State = "pause" | "resume" | "stop";
declare class UpdateStateCommand extends AbstractCommand {
category: CommandInterface["category"];
command: CommandInterface["command"];
/**
* Constructs a `print.print_speed` command, which is able to change the state of the printer, aka stop, resume or pause it.
* @param state {State} The new state of the printer.
*/
constructor({ state }: {
state: State;
});
ownsResponse: typeof isUpdateStateCommand;
}
type PrintMessageCommands = "push_status" | "ams_control" | State | "gcode_line" | "gcode_file" | "project_file";
type PrintMessageCommand = {
command: PrintMessageCommands;
param?: string;
sequence_id: string;
};
interface PrintMessage {
print: PrintMessageCommand;
}
declare function isPrintMessage(data: any): data is PrintMessage;
interface GCodeFileResponse extends PrintMessageCommand {
command: "gcode_file";
param: `${string}.code`;
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
}
declare function isGcodeFileCommand(data: PrintMessageCommand): data is GCodeFileResponse;
interface GCodeLineResponse extends PrintMessageCommand {
command: "gcode_line";
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
return_code: StringNumber;
sequence_id: StringNumber;
}
declare function isGCodeLineCommand(data: PrintMessageCommand): data is GCodeLineResponse;
interface ProjectFileResponse extends PrintMessageCommand {
command: "project_file";
/**
* The location of the project file.
*/
param: `Metadata/${string}.gcode`;
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
subtask_name: `${number}.3mf`;
}
declare function isProjectFileCommand(data: PrintMessageCommand): data is ProjectFileResponse;
interface PushStatusResponse extends Partial<PushAllResponse> {
command: "push_status";
sequence_id: StringNumber;
}
declare function isPushStatusCommand(data: PrintMessageCommand): data is PushStatusResponse;
/**
* Reports all sensors and statuses of the printer.
*/
interface PushAllResponse extends PrintMessageCommand {
/**
* Status of all connected AMSes.
*/
ams: {
ams: [] | [AMS] | [AMS, AMS] | [AMS, AMS, AMS] | [AMS, AMS, AMS, AMS];
/**
* Unknown.
*
* Probably used for checking for new AMSes.
*/
ams_exist_bits: StringNumber;
/**
* Unknown.
*
* Could possibly be related to storing whether the filament's data has been read from the AMSes.
*/
insert_flag: boolean;
/**
* Exact definition is unknown, but it appears to be used for checking if all filaments have been read since startup or not.
*/
power_on_flag: boolean;
/**
* Unknown.
*
* Probably used for checking for new AMSes.
*/
tray_exist_bits: StringNumber;
/**
* Unknown.
*
* Probably used for checking for new AMSes.
*/
tray_is_bbl_bits: StringNumber;
/**
* Current tray selected by all AMSes.
* - 254: external spool (vt_tray)
* - otherwise: ((ams_id * 4) + tray_id) for current tray
*
* @example Ams 2 tray 2 would be: (1*4)+1 = 5.
*/
tray_now: StringNumber;
/**
* Unknown.
*
* Probably used for checking which filament slots (trays) have already been read.
*/
tray_read_done_bits: StringNumber;
/**
* Unknown.
*
* Probably used for signalling which filament slots (trays) are currently being read.
*/
tray_reading_bits: StringNumber;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
tray_tar: StringNumber;
/**
* Unknown.
*
* Could possibly be related to the AMS UI on the X1 series and in Bambu Studio.
*/
version: number;
};
/**
* The RFID reader status of the connected AMSes.
*/
ams_rfid_status: AmsRFIDStatus;
/**
* The AMS status.
*
* How to extract it: https://github.com/bambulab/BambuStudio/blob/f96b6cd433cf925e9759260925cd2142abf298ef/src/slic3r/GUI/DeviceManager.cpp#L736-L759
*
* TODO: Extract when received from printer / provide helper function to do so.
*/
ams_status: number;
/**
* The target temperature of the printing bed in Celsius.
*/
bed_target_temper: number;
/**
* The temperature of the printing bed in Celsius.
*/
bed_temper: number;
/**
* Speed of the auxiliary fan in %.
*/
big_fan1_speed: StringNumberRange<0, 100>;
/**
* Speed of the chamber fan in %.
*/
big_fan2_speed: StringNumberRange<0, 100>;
/**
* Interior chamber temperature.
*/
chamber_temper: number;
/**
* The interior chamber's target temperature.
*
* Exists on the X1 series but only used on the X1E.
*/
ctt: number;
/**
* `chamber_temper` doesn't make sense on P1 series (due to it not being enclosed
* by default) hence the `frame_temper` property.
*
* Even though `chamber_temper` exists, there is no physical sensor for it, but it is still included for some reason.
*
* The value of `chamber_temper` on the P1 series is a placeholder.
*/
frame_temper: number;
/**
* The command the response corresponds to.
*/
command: "push_status";
/**
* Speed of the part cooling fan in %.
*/
cooling_fan_speed: StringNumberRange<0, 100>;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
fail_reason: StringNumber;
/**
* Array of filament backup groups. Each number is a bitmap where each bit represents
* an AMS slot that can be used as backup for that filament group. Compatible slots
* (same filament type and color) are grouped together.
*
* For example, if slots 0 and 4 contain the same filament type and color,
* they would be in the same group with bitmap value 17 (binary: 0001 0001).
*/
filam_bak: number[];
/**
* Contains the current speed of all the fans
*
* How to extract it: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L3273-L3279
*
* TODO: Extract when received from printer / provide helper function to do so.
*/
fan_gear: number;
/**
* Something related to the firmware upgrades.
*/
force_upgrade: boolean;
/**
* Name of the GCode file that is currently printing.
*
* In most cases it's in the format "/plate_#.gcode", unless printing a
* gcode file directly (bbl.gcode, or calibration gcodes) instead of a 3mf.
*/
gcode_file: string;
/**
* % of GCode prepared (sliced?)
*/
gcode_file_prepare_percent: StringNumberRange<0, 100>;
/**
* Epoch time when the print started.
*/
gcode_start_time: StringNumber;
/**
* The current status of the printer.
*/
gcode_state: PrinterStatus;
/**
* Fan speed in %
*
* Heat break fan: The smaller fan on the hotend itself
*/
heatbreak_fan_speed: StringNumberRange<0, 100>;
/**
* Bambu Lab's proprietary Health Management System (HMS)
*
* More info: https://wiki.bambulab.com/en/x1/troubleshooting/intro-hms
*
* All error codes: https://wiki.bambulab.com/en/hms/home
*/
hms: HMS[];
/**
* This single property houses a lot of data regarding the printer.
* There's currently no documentation for it except Bambu Studio's source code:
*
* - Check if axes are homed: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1255-L1269
* - Check if printer is using 220V: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1346-L1351
* - Check if camera is currently recording: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1353
* - Check if AI camera detected filament entanglement: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1368
* - Check if motor noise cancellation has been calibrated: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1376-L1378
* - Check if the current machine is a P1P and has the enclosure enabled: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1380-L1387
* - Check current SD card state (has a lot more info than the sdcard property): https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1389
* - Check if printer is using wired network (ethernet; X1E exclusive): https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1391
*/
home_flag: number;
hw_switch_state: number;
/**
* The printer's onboard camera.
*/
ipcam: {
/**
* The IP and path to the LAN liveview, otherwise disabled.
* @version X1 series exclusive
*/
liveview: string | "disable";
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
tukt_server: string;
/**
* 0: Doesn't have camera
* 1: Has camera
*/
ipcam_dev: StringNumberRange<0, 1>;
/**
* Whether recording while printing is enabled.
*/
ipcam_record: "enable" | "disable";
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
mode_bits: 3;
/**
* The camera's resolution
*
* The value is known to be very weird on the A1 series.
*/
resolution: "720p" | "1080p" | string;
/**
* Whether creating a timelapse while printing is enabled.
*/
timelapse: "enable" | "disable";
};
/**
* Current layer number while printing.
*/
layer_num: number;
/**
* Probably to differentiate between in-house prototypes and production machines.
*/
lifecycle: "product" | "engineer";
/**
* Internal light states
*/
lights_report: LightReport[];
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
maintain: number;
/**
* % of print done
*/
mc_percent: NumberRange<0, 100>;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*
* Perhaps the current GCode line while printing?
*/
mc_print_line_number: StringNumber;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
mc_print_error_code: "0" | StringNumber;
/**
* Something to do with signalling if calibration is done according to source code
*
* https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1331-L1342
*/
mc_print_stage: StringNumberRange<1, 3>;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
mc_print_sub_stage: number;
/**
* Remaining time from print.
*/
mc_remaining_time: number;
/**
* Probably to differentiate between in-house prototypes and production machines
*/
mess_production_state: "active" | "inactive";
/**
* - 0: Full (pushAll) message
* - 1: Partial (pushStatus) "difference" message (only changed properties are sent)
*
* @deprecated Unavailable on the X1 series in LAN mode.
*
* You can instead use isPushAllCommand or isPushStatusCommand from /responses or create a new PushAllCommand and PushStatus command from /commands and use their ownsResponse method for consistency.
*/
msg: NumberRange<0, 1>;
/**
* The target temperature of the nozzle in Celsius.
*/
nozzle_target_temper: number;
/**
* The temperature of the nozzle in Celsius.
*/
nozzle_temper: number;
/**
* Signals the status of some components of the printer and/or accessories.
*/
online: {
/**
* Unknown.
*/
ahb: boolean;
/**
* The RFID reader.
*/
rfid: boolean;
/**
* Unknown.
*/
version: number;
};
/**
* Unknown. Some error code standard which isn't defined in Bambu Studio.
*
* These codes can be cleared using `system.clean_print_error` command.
*/
print_error: number;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
print_gcode_action: number;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
print_real_action: number;
/**
* Where the print originates from.
*/
print_type: "cloud" | "system" | "local" | "idle";
/**
* Unknown. Something related to what's being printed.
*/
profile_id: StringNumber;
/**
* Unknown. Something related to what's being printed.
*/
project_id: StringNumber;
/**
* Unknown. Something related to a print queue. (?)
*/
queue_est: number;
/**
* Unknown. Something related to a print queue. (?)
*/
queue_number: number;
/**
* Unknown. Something related to a print queue. (?)
*/
queue_sts: number;
/**
* Unknown. Something related to a print queue. (?)
*/
queue_total: number;
/**
* Objects that have been skipped by the printer while printing,
*/
s_obj: unknown[];
/**
* Whether the SD card is inserted.
*/
sdcard: boolean;
/**
* Related to general MQTT commands on all Bambu Lab printers. Incremented by one each response/request.
*/
sequence_id: StringNumber;
/**
* The current speed level.
*/
spd_lvl: SpeedLevel;
/**
* The current speed level in %.
*/
spd_mag: NumberRange<50, 166>;
/**
* An x (unknown) amount of previous stages.
*/
stg: PrintStage[];
/**
* The current print stage.
*/
stg_cur: PrintStage;
/**
* Main purpose is unknown.
* - 0: printing from SD card
*/
subtask_id: StringNumber;
/**
* The name of the calibration gcode (without file extension), or the project file name (.3mf - with file extension)
*/
subtask_name: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
task_id: StringNumber;
/**
* Total layer number of the current job.
*/
total_layer_num: number;
/**
* Firmware upgrade status data of the printer.
*/
upgrade_state: {
/**
* Unknown.
*
* Some component's new version number.
*/
ahb_new_version_number: string;
/**
* The new version number of the AMS(es).
*/
ams_new_version_number: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
consistency_request: boolean;
/**
* What the display should say in the process.
*/
dis_state: UpgradeDisplayState;
/**
* Error codes thrown by the upgrade.
*/
err_code: UpgradeErrorCode;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*
* Probably has something to do with an update the user can't deny. (for ex.: security vulnerabilities)
*/
force_upgrade: boolean;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
message: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
module: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
new_ver_list: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
new_version_state: number;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
ota_new_version_number: string;
/**
* The progress of the update in %.
*/
progress: StringNumberRange<0, 100>;
/**
* Incremented by one every time a new status is returned.
*/
sequence_id: number;
/**
* The progress / finish states of the upgrade.
*/
status: UpgradeStatusProgressState & UpgradeStatusFinishState;
};
/**
* Print file download status data.
*/
upload: {
/**
* Downloaded file size (?)
*/
file_size: number;
/**
* Total file size (?)
*/
finish_size: number;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
message: string;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
oss_url: string;
/**
* The progress of the file download in %.
*/
progress: StringNumberRange<0, 100>;
/**
* Incremented by one every time a new status is returned.
*/
sequence_id: StringNumber;
/**
* Download speed in unknown units.
*/
speed: number;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
status: "idle" | string;
/**
* Unknown. Bambu Studio doesn't even check for it.
*/
task_id: string;
/**
* Time remaining until download completes in unknown units.
*/
time_remaining: number;
/**
* Unknown. Bambu Studio doesn't even check for it.
*
* Probably some kind of error code.
*/
trouble_id: string;
};
/**
* External spool (tray). This has unused values due to being a copy of the AMS trays.
*/
vt_tray: ExternalTray;
/**
* The signal strength of the Wi-Fi signal which the printer is connected to in dBm.
*/
wifi_signal: `-${number}dBm`;
/**
* AI-related features of the printer's camera.
*/
xcam: {
/**
* Whether skipping parts setting is enabled.
*/
allow_skip_parts: boolean;
/**
* Whether the printer should detect the correct orientation and type of the buildplate.
*/
buildplate_marker_detector: boolean;
/**
* Whether the first layer inspection is enabled for the printer.
*/
first_layer_inspector: boolean;
/**
* Whether the printer is allowed to stop the print in the event it detects an abnormality.
*/
print_halt: boolean;
/**
* The sensitivity for the spaghetti detector, first layer inspection, etc.
*/
halt_print_sensitivity: "low" | "medium" | "high";
/**
* Whether print monitoring is enabled.
*/
printing_monitor: boolean;
/**
* Whether the spaghetti detector is enabled.
*/
spaghetti_detector: boolean;
};
/**
* AI-related features' status.
*/
xcam_status: StringNumber;
}
type PrinterStatus = "FINISH" | "FAILED" | "RUNNING" | "IDLE" | "PAUSE" | "PREPARE" | "SLICING";
/**
* Detailed information about a print stage
*/
interface PrintStageInfo {
/** The current stage of printing */
stage: PrintStage;
/** Progress percentage within the current stage (0-100) */
progress: number;
/** Human-readable name of the stage */
name: string;
/** Detailed description of what's happening in this stage */
description: string;
/** Whether this stage can be controlled (paused/resumed/skipped) */
controllable: boolean;
/** Whether this stage is critical for print success */
critical: boolean;
/** Estimated time remaining in this stage (seconds) */
timeRemaining?: number;
}
/**
* Every stage of a print.
* Extracted from https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp
*/
declare enum PrintStage {
"PRINTING" = "Printing",
"BED_LEVELING" = "Auto bed leveling",
"HEATBED_PREHEATING" = "Heatbed preheating",
"XY_MECH_MODE_SWEEP" = "Sweeping XY mech mode",
"CHANGE_MATERIAL" = "Changing filament",
"M400_PAUSE" = "M400 pause",
"FILAMENT_RUNOUT_PAUSE" = "Paused due to filament runout",
"HOTEND_HEATING" = "Heating hotend",
"EXTRUDE_COMPENSATION_SCAN" = "Calibrating extrusion",
"BED_SCAN" = "Scanning bed surface",
"FIRST_LAYER_SCAN" = "Inspecting first layer",
"BE_SURFACE_TYPT_IDENTIFICATION" = "Identifying build plate type",
"SCANNER_EXTRINSIC_PARA_CALI" = "Calibrating Micro Lidar",
"TOOLHEAD_HOMING" = "Homing toolhead",
"NOZZLE_TIP_CLEANING" = "Cleaning nozzle tip",
"EXTRUDER_TEMP_PROTECT_CALI" = "Checking extruder temperature",
"USER_PAUSE" = "Printing was paused by the user",
"TOOLHEAD_SHELL_OFF_PAUSE" = "Pause of front cover falling",
"SCANNER_LASER_PARA_CALI" = "Calibrating the micro lida",
"EXTRUDER_ABSOLUTE_FLOW_CALI" = "Calibrating extrusion flow",
"HOTEND_TEMPERATURE_ERROR_PAUSE" = "Paused due to nozzle temperature malfunction",
"HEATED_BED_TEMPERATURE_ERROR_PAUSE" = "Paused due to heat bed temperature malfunction",
"FILAMENT_UNLOADING" = "Filament unloading",
"SKIP_STEP_PAUSE" = "Skip step pause",
"FILAMENT_LOADING" = "Filament loading",
"MOTOR_NOISE_CALIBRATION" = "Motor noise calibration",
"AMS_LOST_PAUSE" = "Paused due to AMS lost",
"HEAT_BREAK_FAN_PAUSE" = "Paused due to low speed of the heat break fan",
"CHAMBER_TEMPERATURE_CONTROL_ERROR_PAUSE" = "Paused due to chamber temperature control error",
"CHAMBER_COOLING" = "Cooling chamber",
"USER_INSERT_GCODE_PAUSE" = "Paused by the Gcode inserted by user",
"MOTOR_NOISE_SHOWOFF" = "Motor noise showoff",
"NOZZLE_FILAMENT_COVERED_DETECTED_PAUSE" = "Nozzle filament covered detected pause",
"CUTTER_ERROR_PAUSE" = "Cutter error pause",
"FIRST_LAYER_ERROR_PAUSE" = "First layer error pause",
"NOZZLE_CLOG_PAUSE" = "Nozzle clog pause"
}
/**
* Maps print stages to their detailed information
*/
/**
* Maps numeric stage_curr values to PrintStage enum values
*/
declare const stageCurrToStage: Record<number, PrintStage>;
declare const PrintStageDetails: Record<PrintStage, Partial<PrintStageInfo>>;
/**
* Speed levels of the printer.
*
* Extracted from https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.hpp#L73-L80
*/
declare enum SpeedLevel {
SILENT = "1",
NORMAL = "2",
SPORT = "3",
LUDICROUS = "4"
}
/**
* An AMS instance.
*/
interface AMS {
humidity: string;
id: string;
temp: string;
tray: [
AMSTray | undefined,
AMSTray | undefined,
AMSTray | undefined,
AMSTray | undefined
];
}
/**
* An AMS tray (filament slot) instance.
*/
interface AMSTray {
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
bed_temp: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
bed_temp_type: string;
/**
* Unknown. Bambu Studio doesn't even check for it.
*
* Probably the temperature required for filament drying.
*/
drying_temp: string;
/**
* Probably the time required for filament drying.
*/
drying_time: string;
/**
* The ID of the tray.
*/
id: string;
/**
* The loaded filament's maximum nozzle temperature.
*/
nozzle_temp_max: StringNumber;
/**
* The loaded filament's minimum nozzle temperature.
*/
nozzle_temp_min: StringNumber;
/**
* The amount filament remaining in %, if enabled and an official Bambu filament is loaded.
*
* With non-official Bambu filament:
* - 0: Tracking is disabled.
* - -1: Tracking is enabled.
*/
remain: number;
/**
* The UID of the filament's NFC that was scanned.
*
* Uses:
* - Check if filament's manufacturer is Bambu Lab: https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L1090-L1101
*
* TODO: Extract when received from printer / provide helper function to do so.
*/
tag_uid: string;
/**
* The color of the filament loaded in HEX color code.
*/
tray_color: string;
/**
* The diameter of the spool loaded.
*/
tray_diameter: 1.75;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
tray_id_name: string;
/**
* The ID of the base config file for the filament.
*
* Uses:
* - Associate the filament loaded with it's complete brand name. Use the `getFilamentConfig` function for getting the config.
*
* Config files can be found here: https://github.com/bambulab/BambuStudio/tree/master/resources/profiles/BBL/filament
*/
tray_info_idx: string;
/**
* No use cases are known.
*/
tray_sub_brands: "";
/**
* The type of filament loaded into the tray (filament slot).
*/
tray_type: FilamentType;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
tray_uuid: string;
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
tray_weight: string;
/**
* Information about the AI camera features (?)
*/
xcam_info: string;
}
/**
* External spool (tray). This has unused values due to being a copy of the AMS trays.
*/
interface ExternalTray extends AMSTray {
/**
* Unknown. Bambu Studio appears to do nothing with it.
*/
cols: StringNumber[];
/**
* The ID of the tray.
*/
id: "254";
/**
* The loaded filament's "k" value (manually set in Bambu Studio).
*/
k: number;
/**
* The loaded filament's "n" value (manually set in Bambu Studio).
*/
n: number;
}
/**
* Status of the AMS' RFID reader.
*/
declare enum AmsRFIDStatus {
IDLE = 0,
READING = 1,
GCODE_TRANS = 2,
GCODE_RUNNING = 3,
ASSISTANT = 4,
SWITCH_FILAMENT = 5,
HAS_FILAMENT = 6
}
/**
* Bambu Lab's proprietary Health Management System (HMS).
*
* More info: https://wiki.bambulab.com/en/x1/troubleshooting/intro-hms
*
* All error codes: https://wiki.bambulab.com/en/hms/home
*/
interface HMS {
attr: number;
code: number;
}
/**
* Interior lighting related status instance.
*/
interface LightReport {
node: "chamber_light" | "work_light";
mode: "on" | "off" | "flashing";
}
/**
* The possible progress states of a firmware upgrade.
*
* Extracted from https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L3481-L3494
*/
declare enum UpgradeStatusProgressState {
DOWNLOADING = "DOWNLOADING",
UPGRADE_REQUEST = "UPGRADE_REQUEST",
PRE_FLASH_START = "PRE_FLASH_START",
PRE_FLASH_SUCCESS = "PRE_FLASH_SUCCESS"
}
/**
* The possible finish states of a firmware upgrade.
*
* Extracted from https://github.com/bambulab/BambuStudio/blob/master/src/slic3r/GUI/DeviceManager.cpp#L3481-L3494
*/
declare enum UpgradeStatusFinishState {
UPGRADE_SUCCESS = "UPGRADE_SUCCESS",
DOWNLOAD_FAIL = "DOWNLOAD_FAIL",
FLASH_FAIL = "FLASH_FAIL",
PRE_FLASH_FAIL = "PRE_FLASH_FAIL",
UPGRADE_FAIL = "UPGRADE_FAIL"
}
/**
* Error codes thrown by the upgrade.
*/
declare enum UpgradeErrorCode {
UpgradeNoError = 0,
UpgradeDownloadFailed = 1,
UpgradeVerifyFailed = 2,
UpgradeFlashFailed = 3,
UpgradePrinting = 4
}
/**
* The possible states the printer's screen will display.
*/
declare enum UpgradeDisplayState {
UNAVAILABLE = 0,
IDLE = 1,
UPGRADING = 2,
UPGRADE_FINISHED = 3
}
declare enum FilamentType {
PLA = "PLA",
ABS = "ABS",
TPU = "TPU",
PC = "PC",
ASA = "ASA",
PA_CF = "PA-CF",
PA6_CF = "PA6-CF",
PET_CF = "PET-CF",
PETG = "PETG",
PETG_CF = "PETG-CF",
PLA_AERO = "PLA-AERO",
PLA_CF = "PLA-CF",
PPA_CF = "PPA-CF",
PPA_GF = "PPA-GF",
PA = "PA",
HIPS = "HIPS",
PPS = "PPS",
PPS_CF = "PPS-CF",
PVA = "PVA",
PLA_S = "PLA-S",
PA_S = "PLA-S"
}
/**
* Contains basic data about a filament, which is then extended by the final product.
*/
interface BaseFilamentConfig {
type: "filament";
name: string;
inherits: string;
from: string;
instantiation: StringBoolean;
fan_cooling_layer_time: [StringNumber];
filament_max_volumetric_speed: [StringNumber];
filament_density: [StringNumber];
filament_cost: [StringNumber];
cool_plate_temp: [StringNumber];
eng_plate_temp: [StringNumber];
hot_plate_temp: [StringNumber];
textured_plate_temp: [StringNumber];
cool_plate_temp_initial_layer: [StringNumber];
eng_plate_temp_initial_layer: [StringNumber];
hot_plate_temp_initial_layer: [StringNumber];
textured_plate_temp_initial_layer: [StringNumber];
nozzle_temperature_initial_layer: [StringNumber];
reduce_fan_stop_start_freq: [StringNumber];
fan_min_speed: [StringNumber];
overhang_fan_threshold: [StringNumber];
close_fan_the_first_x_layers: [StringNumber];
nozzle_temperature: [StringNumber];
temperature_vitrification: [StringNumber];
nozzle_temperature_range_low: [StringNumber];
nozzle_temperature_range_high: [StringNumber];
slow_down_min_speed: [StringNumber];
slow_down_layer_time: [StringNumber];
additional_cooling_fan_speed: [StringNumber];
filament_start_gcode: [string];
}
/**
* The config files ending with @base
*/
interface ExtendedFilamentConfig extends Partial<BaseFilamentConfig> {
type: "filament";
name: string;
inherits: string;
from: string;
filament_id: string;
setting_id: string;
}
/**
* The final filament config data. Contains the inherited and @base file data.
*/
interface FilamentConfig extends BaseFilamentConfig {
type: "filament";
name: string;
inherits: string;
from: string;
filament_id: string;
instantiation: StringBoolean;
filament_cost: [StringNumber];
filament_vendor: [string];
}
/**
* Retrieves the FilamentConfig object associated with the specified ID.
* @param id - The ID of the FilamentConfig to retrieve.
* @returns The FilamentConfig object if found, otherwise undefined.
*/
declare function getFilamentConfig(id: string): FilamentConfig | null;
/**
* Converts a numeric stage_curr value to its corresponding PrintStage enum value
* @param stageCurr - The numeric stage value (0-35)
* @returns The corresponding PrintStage enum value, or undefined if not found
*/
declare function getStageFromCurr(stageCurr: number): PrintStage | undefined;
/**
* Converts an array of numeric stage values to an array of PrintStage enum values
* @param stages - Array of numeric stage values (0-35)
* @returns Array of corresponding PrintStage enum values, filtering out any undefined stages
*/
declare function getStagesFromArray(stages: number[]): PrintStage[];
/**
* Represents a stage with its details and completion status
*/
interface EnrichedStageInfo extends Partial<PrintStageInfo> {
stage: PrintStage;
description: string;
completed: boolean;
current: boolean;
}
/**
* Creates an enriched array of stage information with completion status
* @param currentStage - The current stage number (stage_curr)
* @param stageHistory - Array of previous stage numbers (stg)
* @returns Array of stages with their details and completion status
*
* @example
* const stages = getEnrichedStages(4, [2, 13, 24, 4]);
* // Returns array of EnrichedStageInfo with:
* // - HEATBED_PREHEATING (completed)
* // - TOOLHEAD_HOMING (completed)
* // - FILAMENT_LOADING (completed)
* // - CHANGE_MATERIAL (current, not completed)
*/
declare function getEnrichedStages(currentStage: number, stageHistory: number[]): EnrichedStageInfo[];
declare function isPushAllCommand(data: PrintMessageCommand): data is PushAllResponse;
interface UpdateFanResponse extends PrintMessageCommand {
command: "gcode_line";
param: string;
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
}
declare function isUpdateFanCommand(data: PrintMessageCommand): data is UpdateFanResponse;
interface UpdateLightResponse extends PushStatusResponse {
param: string;
lights_report: LightReport[];
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
}
declare function isUpdateLightCommand(data: PrintMessageCommand): data is UpdateLightResponse;
interface UpdateSpeedResponse extends PushStatusResponse {
param: string;
spd_lvl: SpeedLevel;
spd_mag: NumberRange<50, 166>;
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
}
declare function isUpdateSpeedCommand(data: PrintMessageCommand): data is UpdateSpeedResponse;
interface UpdateStateResponse extends PrintMessageCommand {
command: State;
param: string;
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
}
declare function isUpdateStateCommand(data: PrintMessageCommand): data is UpdateStateResponse;
interface UpdateTempResponse extends PrintMessageCommand {
command: "gcode_line";
param: string;
reason: "SUCCESS" | "FAILURE" | string;
result: "SUCCESS" | "FAILURE" | string;
sequence_id: StringNumber;
}
declare function isUpdateTempCommand(data: PrintMessageCommand): data is UpdateTempResponse;
type MCPrintMessageCommands = "push_info";
type MCPrintMessageCommand = {
command: MCPrintMessageCommands;
sequence_id: string;
};
interface MCPrintMessage {
print: MCPrintMessageCommand;
}
declare function isMCPrintMessage(data: any): data is MCPrintMessage;
interface PushInfoResponse extends MCPrintMessageCommand {
command: "push_info";
param: string;
sequence_id: StringNumber;
}
declare function isPushInfoCommand(data: MCPrintMessageCommand): data is PushInfoResponse;
interface CleanPushInfoCommand {
category: string;
content: string;
rawParam: string;
sequenceId: number;
subcategory?: string;
}
declare function getCleanPushInfoCommand(command: PushInfoResponse): CleanPushInfoCommand;
type InfoMessageCommands = "get_version";
type InfoMessageCommand = {
command: InfoMessageCommands;
sequence_id: string;
};
interface InfoMessage {
info: InfoMessageCommand;
}
declare function isInfoMessage(data: any): data is InfoMessage;
interface VersionModule {
/**
* The module's name.
*/
name: string;
/**
* The module's hardware version.
*/
hw_ver: string;
/**
* The module's serial number.
*/
sn: string;
/**
* The module's software version.
*/
sw_ver: string;
}
interface GetVersionResponse extends InfoMessageCommand {
command: "get_version";
module: VersionModule[];
sequence_id: StringNumber;
}
declare function isGetVersionCommand(data: InfoMessageCommand): data is GetVersionResponse;
interface AMSFilamentSettingResponse {
command: "ams_filament_setting";
result: "success" | "failed";
info?: string;
sequence_id: string;
}
declare function isAMSFilamentSettingResponse(response: {
command: string;
sequence_id: string;
}, commandSeqId: string): response is AMSFilamentSettingResponse;
type StringNumber = `${number}`;
type StringBoolean = `${boolean}`;
type NumberRange<start extends number, end extends number, arr extends unknown[] = [], acc extends number = never> = arr["length"] extends end ? acc | start | end : NumberRange<start, end, [
...arr,
1
], arr[start] extends undefined ? acc : acc | arr["length"]>;
type StringNumberRange<F extends number, T extends number> = `${NumberRange<F, T>}`;
interface IncomingMessageData {
[key: string]: unknown;
}
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
interface PrinterData extends Optional<PushStatusResponse, "command" | "sequence_id"> {
modules: VersionModule[];
model: PrinterModelNamesShort | undefined;
}
type ValueOf<T> = T[keyof T];
type CommandResponse = InfoMessageCommand | MCPrintMessageCommand | PrintMessageCommand | AMSFilamentSettingResponse;
type BambuClientPrinterStatus = PrinterStatus | "OFFLINE";
type IConnackPacket = mqtt.IConnackPacket;
declare enum PrinterModelNamesShort {
X1C = "X1C",
X1 = "X1",
X1E = "X1E",
P1P = "P1P",
P1S = "P1S",
A1 = "A1",
A1M = "A1M"
}
/**
* Represents a single print job.
*/
declare class Job {
private _jobData;
constructor(data: PushAllResponse, printerId: string, printerModel: PrinterModelNamesShort, createdAt?: Date);
/**
* Updates the job with new (up-to-date) data.
*/
update(data: Partial<PushAllResponse>): void;
get data(): JobData;
}
/**
* Represents the properties of a job.
*
* WARNING: Only values which are key information when the job finishes should be added here.
*/
interface JobData {
/**
* The unique CUID of the job.
*/
id: string;
/**
* The ID of the printer who created this job.
*/
printerId: string;
/**
* The model of the printer who created this job.
*/
printerModel: PrinterModelNamesShort;
/**
* The name of the job.
*
* Uses the `subtask_name` property and strips any file extensions.
* @see PushAllCommand["subtask_name"]
*/
name: string;
/**
* The file name of the job.
*
* The `subtask_name` property.
* @see PushAllCommand["subtask_name"]
*/
fileName: PushAllResponse["subtask_name"];
/**
* The name of the GCode which gets executed.
* @see PushAllCommand["gcode_file"]
*/
gcodeName: PushAllResponse["gcode_file"];
/**
* The origin of the job.
* @see PushAllCommand["print_type"]
*/
jobOrigin: PushAllResponse["print_type"];
/**
* The total layer number of the job.
*/
totalLayerNumber: PushAllResponse["total_layer_num"];
/**
* The total print time the Job takes to print in minutes.
*/
totalPrintTime: PushAllResponse["mc_remaining_time"];
/**
* The status of the job (printer).
*/
status: PushAllResponse["gcode_state"];
/**
* The current stage of the print job.
*/
stage: PrintStage;
/**
* The % of the print done from the job.
*/
percentDone: PushAllResponse["mc_percent"];
/**
* The current layer number.
*/
layerNumber: PushAllResponse["layer_num"];
/**
* The remaining time until the job finishes in minutes.
*/
remainingTime: PushAllResponse["mc_remaining_time"];
/**
* Objects that have been skipped by the printer while printing.
* @see PushStatusCommand["s_obj"]
*/
skippedObjects: PushAllResponse["s_obj"];
/**
* Stores the status changes throughout the job.
*/
statusHistory: StatusChangeItem[];
/**
* Stores the manual speed level changes throughout the job.
*/
speedLevelHistory: SpeedLevelHistoryItem[];
/**
* Stores the printing stage changes throughout the job.
*/
printingStageHistory: PrintingStageHistoryItem[];
/**
* Stores the temperature changes throughout the job. Updated every 5 seconds while printing.
*/
temperatureHistory: TemperatureHistoryItem[];
/**
* The last time the temperature was updated. Used internally to ensure that we only update every 5 seconds.
*/
tempLastUpdatedAt: Date;
/**
* The HMS error codes the printer encountered while printing the Job.
*/
errorCodes: HMSCodeHistory[];
/**
* The date time the job (print) started.
*/
createdAt: Date;
}
/**
* A status change instance.
*/
interface StatusChangeItem {
status: PrinterStatus;
changedAt: Date;
}
/**
* A manual speed level change instance.
*/
interface SpeedLevelHistoryItem {
speedLevel: PushAllResponse["spd_lvl"];
speedMagnitude: PushAllResponse["spd_mag"];
changedAt: Date;
}
/**
* A printing stage change instance with detailed information.
*/
interface PrintingStageHistoryItem {
stage: PrintStage;
progress: number;
name: string;
description: string;
controllable: boolean;
critical: boolean;
timeRemaining?: number;
changedAt: Date;
}
interface TemperatureHistoryItem {
bedTemp: number;
bedTargetTemp: number;
/**
* `frame_temper` or `chamber_temper` depending on the printer model.
*/
interiorTemp: number;
nozzleTemp: number;
nozzleTargetTemp: number;
changedAt: Date;
}
interface HMSCodeHistory extends HMS {
/**
* The time the error code was thrown.
*/
thrownAt: Date;
/**
* The layer number the error code was thrown at.
*/
layerNumber: number;
}
type FinishOutcome = "SUCCESS" | "FAILED" | "UNEXPECTED";
interface BambuClientEvents {
message: [topic: string, key: string, data: IncomingMessageData];
rawMessage: [topic: string, payload: Buffer];
"client:connect": [];
"client:disconnect": [isDisconnectOffline: boolean];
"client:error": [error: Error];
"printer:dataUpdate": [data: PrinterData, updatePackage: Partial<PrinterData>];
"printer:statusUpdate": [
oldStatus: BambuClientPrinterStatus,
newStatus: BambuClientPrinterStatus
];
"printer:amsUpdate": [ams: PushAllResponse["ams"]];
"job:update": [job: Job, updatePackage: Partial<JobData>];
"job:start": [job: Job];
"job:pause": [job: Job, isClientOffline: boolean];
"job:offlineRecovery": [job: Job];
"job:unpause": [job: Job];
"job:finish": [job: Job, outcome: FinishOutcome];
}
interface BambuClientOptions {
/**
* The IP address / URL of the printer.
*/
host: string;
/**
* The port of the printer.
* @default 8883
*/
port?: number;
/**
* The access token of the printer.
* It can be found in the settings.
*/
accessToken: string;
/**
* The serial number of the printer.
* It can be found in the settings or the back sticker.
*/
serialNumber: string;
/**
* Whether to throw errors while running `publish` and `executeCommand` methods when offline.
* @default false
*/
throwOnOfflineCommands?: boolean;
/**
* The time between 2 reconnection attempts in ms.
* @default 1000
*/
reconnectInterval?: number;
/**
* The time to wait before a `CONNACK` is received in ms.
* @default 2000
*/
connectTimeout?: number;
/**
* The amount of time that keep alive will consider the server inactive in seconds.
*
* Please note: numbers lower than 20 usually make the client go into a reconnect loop. If you have an idea on how to fix this then feel free to open a PR / issue.
* @default 20
*/
keepAlive?: number;
/**
* An array of jobs to load into the `jobHistory` array.
*
* You can use any kind of persistent storage to persist jobs and them load them back in to query them if need be.
*/
jobHistory?: Job[];
/**
* The job to load into the `currentJob` array.
*
* You can use any kind of persistent storage to persist jobs and them load them back in to query them if need be.
*/
currentJob?: Job;
}
/**
* Manages connectivity and messages from/to the printer.
*/
declare class BambuClient extends events.EventEmitter<keyof BambuClientEvents> {
readonly clientOptions: BambuClientOptions;
emit<K extends keyof BambuClientEvents>(event: K, ...arguments_: BambuClientEvents[K]): boolean;
off<K extends keyof BambuClientEvents>(event: K, listener?: (...arguments_: BambuClientEvents[K]) => void): this;
once<K extends keyof BambuClientEvents>(event: K, listener: (...arguments_: BambuClientEvents[K]) => void): this;
on<K extends keyof BambuClientEvents>(event: K, listener: (...arguments_: BambuClientEvents[K]) => void): this;
id: string;
private mqttClient;
config: {
host: string;
port: number;
accessToken: string;
serialNumber: string;
throwOnOfflineCommands: boolean;
reconnectInterval: number;
connectTimeout: number;
keepAlive: number;
};
private _printerData;
private _printerStatus;
jobHistory: Job[];
currentJob: Job | null;
private isJobInHistory;
private addJobToHistory;
constructor(clientOptions: BambuClientOptions);
private connectMQTT;
/**
* Connect to the printer.
*/
connect(): Promise<[mqtt.IConnackPacket]>;
/**
* Disconnect from the printer.
* @param force Forcefully disconnect.
* @param options {Parameters<MqttClient["end"]>[1]} MQTT client options
*/
disconnect(force?: boolean, options?: Parameters<MqttClient["end"]>[1]): Promise<unknown>;
private subscribe;
/**
* Execute a command.
* @param command {AbstractCommand} Command to execute.
* @returns {Promise<CommandResponse>} A promise which resolves to the CommandResponse once the command has been acknowledged by the printer, times out after 5 seconds.
*/
executeCommand(command: AbstractCommand, timeoutMs?: number): Promise<CommandResponse>;
protected onConnect(packet: mqtt.IConnackPacket): Promise<mqtt.IConnackPacket>;
private onMessage;
/**
* Used by the individual command types to publish messages to the printer.
* @param message
*/
publish(message: string | object): Promise<void>;
get data(): PrinterData;
get connectionStatus(): boolean | undefined;
get status(): BambuClientPrinterStatus;
}
interface CommandInterface {
category: "info" | "pushing" | "system" | "print";
command: string;
extra?: Record<string, unknown> & {
sequence_id?: string;
};
invoke(client: BambuClient): void;
}
declare abstract class AbstractCommand implements CommandInterface {
extra: CommandInterface["extra"];
abstract category: CommandInterface["category"];
abstract command: CommandInterface["command"];
/**
* Constructs a basic command class with the properties required for basic compatibility with @hiv3d/bambu-node.
* @param extra Extra properties to add to the request object.
*/
protected constructor(extra?: CommandInterface["extra"]);
invoke(client: BambuClient): Promise<string>;
abstract ownsResponse(command: CommandResponse, squence_id?: string): boolean;
}
type GCodeCommandParam = "gcode_file" | "gcode_line";
declare abstract class GCodeCommand extends AbstractCommand {
category: CommandInterface["category"];
abstract command: GCodeCommandParam;
/**
* Constructs a basic `print.gcode_file` or `print.gcode_line` command, which must be extended first to use.
* @param gcode The array of Gcode instructions to execute. Implementation can be overridden if using with `gcode_file`.
* @protected
*/
protected constructor(gcode: string[]);
}
declare class GCodeFileCommand extends AbstractCommand {
category: CommandInterface["category"];
command: CommandInterface["command"];
/**
* Constructs a new GCode file command, which executes a GCode file on the printer's filesystem.
* @param fileName The file name of the GCode to execute on the printer. (on the printer's filesystem)
*/
constructor({ fileName }: {
fileName: string;
});
ownsResponse: typeof isGcodeFileCommand;
}
declare class GCodeLineCommand extends GCodeCommand {
command: GCodeCommandParam;
/**
* Creates a raw GCode line command, which executes an array of GCode instructions on the printer.
* @param gcodes The array of GCode instructions to execute.
*/
constructor({ gcodes }: {
gcodes: string[];
});
ownsResponse: typeof isGCodeLineCommand;
}
declare class GetVersionCommand extends AbstractCommand {
category: CommandInterface["category"];
command: CommandInterface["command"];
/**
* Constructs a new get version command.
*/
constructor();
ownsResponse: typeof isGetVersionCommand;
}
declare class PushAllCommand extends AbstractCommand {
category: CommandInterface["category"];
command: CommandInterface["command"];
/**
* Constructs a new `pushing.pushall` command, which gets all properties from the printer.
* @version
* - X1 series: Already sends `pushing.pushall` responses automatically every ~2 secs.
* - Other series: Only sends partial responses of `pushing.pushall` with only the values that have changed since the last response.
*/
constructor();
ownsResponse: typeof isPushAllCommand;
}
declare enum Fan {
PART_COOLING_FAN = 1,
AUXILIARY_FAN = 2,
CHAMBER_FAN = 3
}
declare class UpdateFanCommand extends GCodeCommand {
command: GCodeCommandParam;
/**
* Constructs a `print.gcode_line` command, which is able to update the current speeds of every fan on the printer.
* @param fan {Fan} The fan's speed to update.
* @param speed {NumberRange<0, 100>} The fan's new speed in % (0-100).
*/
constructor({ fan, speed }: {
fan: Fan;
speed: NumberRange<0, 100>;
});
ownsResponse: typeof isUpdateFanCommand;
}
interface UpdateLightLoopOpt