@hiv3d/bambu-node v3.22.32
Bambu Node
!CAUTION
🚧 This library is still in the making. PRs and other feature requests are welcome.
A node.js library for connecting to and receiving data from Bambu Lab printers through their MQTT servers.
- Every command & response field is documented & typed.
- Easily (and safely*) construct commands & manage responses.
- Full async support!
client#executeCommand
waits until the command completion is verified by the printer.
Getting Started
Prerequisites
Make sure you have the following installed:
- Node.js
- NPM
- TypeScript
!CAUTION
TypeScript is highly recommended for this package due to the type safety it provides. This is especially important in use cases like this project where the library communicates with external hardware which can very well come with property damage. And even with TypeScript, I am not liable for any such damages as stated in the license.
Installation
npm install bambu-node
Example Usage
Understanding the Protocol
Sequence ID
The sequence_id is a critical component of the Bambu Lab printer communication protocol. It ensures reliable, ordered, and secure command processing between the client and printer.
How It Works
- Each command sent to the printer includes a unique sequence_id
- Valid sequence_ids must be between 20000 and 30000
- The sequence_id must be incremented for each new command
- The printer returns responses with the same sequence_id as the original command
Why It's Critical
Command Validation
- The sequence_id range acts as a security measure
- Only commands with valid sequence_ids are processed
- Helps prevent unauthorized command injection
Command-Response Matching
- Responses include the original command's sequence_id
- Allows matching responses to their originating commands
- Essential for asynchronous command processing
Error Handling
- Error responses are matched to commands via sequence_id
- Enables proper error attribution and handling
- Critical for temperature and safety-related commands
State Management
- Maintains proper command ordering
- Prevents command duplication
- Ensures reliable command acknowledgment
Implementation Requirements
- Always increment sequence_id for each new command
- Never reuse sequence_ids within a session
- Validate sequence_ids in responses match sent commands
- Handle sequence_id wraparound when reaching the upper limit
Consequences of Improper Implementation
Failing to properly implement sequence_id management can result in:
- Commands being ignored or rejected
- Incorrect error attribution
- Mixed up command responses
- Failed command acknowledgments
- Compromised safety features
Library Implementation
The library provides a sequenceIdManager
utility that handles sequence IDs according to the protocol specification:
import { getSequenceId, isValidSequenceId, START_SEQ_ID, END_SEQ_ID } from './utils/sequenceIdManager';
// Get next sequence ID (automatically handles wraparound)
const nextId = getSequenceId(); // Returns number between 20000-30000
// Validate incoming sequence IDs
const isValid = isValidSequenceId(nextId); // Returns true if within valid range
// Example usage in commands
async function sendCommand(command: any) {
// Automatically assign next valid sequence ID
command.sequence_id = getSequenceId();
// Send command and validate response sequence_id matches
const response = await sendToDevice(command);
if (!isValidSequenceId(response.sequence_id)) {
throw new Error('Invalid sequence ID in response');
}
if (response.sequence_id !== command.sequence_id) {
throw new Error('Response sequence ID mismatch');
}
return response;
}
The sequence ID management is handled automatically by the library's internal command processing, so you typically don't need to manage it directly when using the public API.
import { BambuClient, Fan, UpdateFanCommand } from "bambu-node"
// define a printer connection
const client = new BambuClient({
host: "your_printers_ip",
accessToken: "your_printers_access_token",
serialNumber: "your_printers_sn",
})
// more about the available events below
client.on("message", (topic, key, data) => {
console.log(`New ${key} message!`, data)
})
client.on("printer:statusUpdate", (oldStatus, newStatus) => {
console.log(`The printer's status has changed from ${oldStatus} to ${newStatus}!`)
})
// connect to the printer
await client.connect()
// update the speed of the auxiliary fan to 100%
await client.executeCommand(new UpdateFanCommand({ fan: Fan.AUXILIARY_FAN, speed: 100 }))
// we don't want to do anything else => we close the connection
// (can be kept open indefinitely if needed)
await client.disconnect()
API
Legend
Unnamed things inside classes: Other classes that extend that class.
Every method, command and response is documented in JSDoc, so only events & utility classes are documented here.
- Bambu Node
- Class:
BambuClient
- Method:
BambuClient.connect()
- Method:
BambuClient.disconnect()
- Method:
BambuClient.subscribe(topic)
- Method:
BambuClient.executeCommand(command)
- Event:
message
- Event:
rawMessage
- Event:
client:connect
- Event:
client:disconnect
- Event:
printer:dataUpdate
- Event:
printer:statusUpdate
- Event:
job:update
- Event:
job:start
- Event:
job:pause
- Event:
job:offlineRecovery
- Event:
job:unpause
- Event:
job:finish
- Method:
- Class:
Job
- Method:
Job.update(data)
- Getter:
Job.data
- Method:
- Class:
AbstractCommand
- Class:
GCodeCommand
GCodeFileCommand
GCodeLineCommand
GetVersionCommand
PushAllCommand
UpdateFanCommand
UpdateLightCommand
UpdateSpeedCommand
UpdateStateCommand
UpdateTempCommand
- Class:
- Command Responses
- info
- Class:
InfoMessageCommand
GetVersionResponse
- Class:
- mcPrint
- Class:
McPrintMessageCommand
PushInfoResponse
- Class:
- print
- Class:
PrintMessageCommand
GCodeFileResponse
GCodeLineResponse
ProjectFileResponse
PushAllResponse
PushStatusResponse
UpdateFanResponse
UpdateLightResponse
UpdateSpeedResponse
UpdateStateResponse
UpdateTempResponse
- Class:
- info
- Class:
Class: BambuClient
Responsible for managing the connection and messages to/from the printer.
Events
rawMessage
Triggered whenever a new message is received from the MQTT broker.
message
Triggered whenever a new known message is received from the MQTT broker. It's already parsed and sent using its type.
client:connect
Triggered whenever the client connects to the printer. This will also trigger on a reconnect.
client:disconnect
Triggered whenever the client disconnects from the printer. This can be on purpose using
the client#disconnect
method or when the printer itself goes offline.
client:error
Triggered whenever the internal MQTT client encounters an error.
Examples include:
- Unresolvable host provided
- Incorrect credentials provided
- Unexpected responses
printer:dataUpdate
Triggered whenever new data is received from the printer and is merged into the data class field.
printer:statusUpdate
Triggered whenever the printer's status changes to a new status.
job:update
Triggered whenever the current Job's data gets updated.
job:start
Triggered whenever a new printing job starts.
job:pause
Triggered whenever the current print job is paused.
job:offlineRecovery
Triggered whenever the current print job was recovered after the printer came back online from an offline state.
job:unpause
Triggered whenever the current print job is resumed.
job:finish
Triggered whenever the current print job finishes.
Possible reasons:
SUCCESS
: Triggered whenever the current print job finishes without errors.FAILED
: Triggered whenever the current print job finishes without errors.UNEXPECTED
: Triggered whenever the current print job finishes unexpectedly. This is only included as a proof of concept and is 99% bound to never happen.
Class: Job
Responsible for managing the data about the current print job. It collects historical
data, error codes, etc. It is included in every event starting with job:
.
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.