Skip to content

Commit 9ac7315

Browse files
authored
[bambulab] Initial contribution (openhab#18369)
* Init BambuLab Signed-off-by: Martin Grześlowski <[email protected]>
1 parent 5ef6840 commit 9ac7315

File tree

19 files changed

+1712
-2
lines changed

19 files changed

+1712
-2
lines changed

CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
/bundles/org.openhab.binding.automower/ @maxpg
3939
/bundles/org.openhab.binding.avmfritz/ @cweitkamp
4040
/bundles/org.openhab.binding.awattar/ @Wolfgang1966
41+
/bundles/org.openhab.binding.bambulab/ @magx2
4142
/bundles/org.openhab.binding.benqprojector/ @mlobstein
4243
/bundles/org.openhab.binding.bigassfan/ @mhilbush
4344
/bundles/org.openhab.binding.bluetooth/ @cdjackson @cpmeister

bom/openhab-addons/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@
181181
<artifactId>org.openhab.binding.awattar</artifactId>
182182
<version>${project.version}</version>
183183
</dependency>
184+
<dependency>
185+
<groupId>org.openhab.addons.bundles</groupId>
186+
<artifactId>org.openhab.binding.bambulab</artifactId>
187+
<version>${project.version}</version>
188+
</dependency>
184189
<dependency>
185190
<groupId>org.openhab.addons.bundles</groupId>
186191
<artifactId>org.openhab.binding.benqprojector</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
This content is produced and maintained by the openHAB project.
2+
3+
* Project home: https://www.openhab.org
4+
5+
== Declared Project Licenses
6+
7+
This program and the accompanying materials are made available under the terms
8+
of the Eclipse Public License 2.0 which is available at
9+
https://www.eclipse.org/legal/epl-2.0/.
10+
11+
== Source Code
12+
13+
https://github.com/openhab/openhab-addons
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# BambuLab Binding
2+
3+
This addon supports connecting with BambuLab 3D printers in local mode.
4+
While cloud mode is theoretically possible, it is not supported by the addon developers.
5+
6+
## Cloud Mode
7+
8+
Cloud mode is possible but not officially supported by the addon developers.
9+
10+
To use cloud mode, follow these steps:
11+
12+
### Find Username
13+
14+
Log in to Maker World and visit [my-preferences](https://makerworld.com/api/v1/design-user-service/my/preference) to retrieve a JSON response containing your data.
15+
The relevant field is `uid`, which represents the unique ID of your account.
16+
Use this value as the `username` in the configuration (advanced field) with the prefix `u_`.
17+
18+
### Access Token
19+
20+
To obtain an access token, follow these steps:
21+
22+
1. Log in using your email and password.
23+
2. Confirm the login using a token received via email.
24+
25+
#### Step 1: Login with Email and Password
26+
27+
```shell
28+
curl -X POST "https://api.bambulab.com/v1/user-service/user/login" \
29+
-H "Content-Type: application/json" \
30+
-d '{
31+
"account": "[email protected]",
32+
"password": "superduperpassword123"
33+
}'
34+
```
35+
36+
#### Step 2: Confirm Login with Token from Email
37+
38+
```shell
39+
curl -X POST "https://api.bambulab.com/v1/user-service/user/login" \
40+
-H "Content-Type: application/json" \
41+
-d '{
42+
"account": "[email protected]",
43+
"code": "123456"
44+
}'
45+
```
46+
47+
You will receive a long access code in the response. Copy it and use it as the `accessCode` parameter.
48+
49+
**Note:** This access code expires after three months. When it expires, repeat the process to obtain a new one.
50+
51+
### Hostname
52+
53+
Use `us.mqtt.bambulab.com` as the hostname.
54+
55+
## Supported Things
56+
57+
- `printer`: Represents a BambuLab 3D printer.
58+
59+
## Thing Configuration
60+
61+
| Parameter | Type | Required | Description |
62+
|--------------|---------|----------|-------------------------------------------------------------------------------------------------|
63+
| `serial` | Text | Yes | Unique serial number of the printer. |
64+
| `scheme` | Text | No | URI scheme. (Advanced) |
65+
| `hostname` | Text | Yes | IP address of the printer or `us.mqtt.bambulab.com` for cloud mode. |
66+
| `port` | Integer | No | URI port. (Advanced) |
67+
| `username` | Text | No | `bblp` for local mode or your Bambu Lab user (starting with `u_`). (Advanced) |
68+
| `accessCode` | Text | Yes | Access code for the printer. The method of obtaining this varies between local and cloud modes. |
69+
70+
## Channels
71+
72+
| Channel ID | Type | Description |
73+
|---------------------------|---------------------|------------------------------------------------------------------|
74+
| `nozzle-temperature` | Temperature Channel | Current temperature of the nozzle. |
75+
| `nozzle-target-temperature` | Temperature Channel | Target temperature of the nozzle. |
76+
| `bed-temperature` | Temperature Channel | Current temperature of the heated bed. |
77+
| `bed-target-temperature` | Temperature Channel | Target temperature of the heated bed. |
78+
| `chamber-temperature` | Temperature Channel | Current temperature inside the printer chamber. |
79+
| `mc-print-stage` | String Channel | Current stage of the print process. |
80+
| `mc-percent` | Percent Channel | Percentage of the print completed. |
81+
| `mc-remaining-time` | Number Channel | Estimated time remaining for the print (in seconds). |
82+
| `wifi-signal` | WiFi Channel | Current WiFi signal strength. |
83+
| `bed-type` | String Channel | Type of the printer's heated bed. |
84+
| `gcode-file` | String Channel | Name of the currently loaded G-code file. |
85+
| `gcode-state` | String Channel | Current state of the G-code execution. |
86+
| `reason` | String Channel | Reason for pausing or stopping the print. |
87+
| `result` | String Channel | Final result or status of the print job. |
88+
| `gcode-file-prepare-percent` | Percent Channel | Percentage of G-code file preparation completed. |
89+
| `big-fan1-speed` | Number Channel | Speed of the first large cooling fan (RPM). |
90+
| `big-fan2-speed` | Number Channel | Speed of the second large cooling fan (RPM). |
91+
| `heat-break-fan-speed` | Number Channel | Speed of the heat break cooling fan (RPM). |
92+
| `layer-num` | Number Channel | Current layer being printed. |
93+
| `speed-level` | Number Channel | Current speed setting of the print job. |
94+
| `time-laps` | Boolean Channel | Indicates whether time-lapse recording is enabled. |
95+
| `use-ams` | Boolean Channel | Indicates whether the Automatic Material System (AMS) is active. |
96+
| `vibration-calibration` | Boolean Channel | Indicates whether vibration calibration has been performed. |
97+
| `led-chamber` | On/Off Command | Controls the LED lighting inside the printer chamber. |
98+
| `led-work` | On/Off Command | Controls the LED lighting for the work area. |
99+
100+
## Full Example
101+
102+
### `bambulab.things` Example
103+
104+
```java
105+
Thing bambulab:printer:myprinter "My BambuLab Printer" @ "3D Printing Area" [
106+
serial="ABC123456789",
107+
hostname="192.168.1.100",
108+
accessCode="your_access_code_here"
109+
]
110+
```
111+
112+
### `bambulab.items` Exmaple
113+
114+
```java
115+
Number:Temperature NozzleTemperature "Nozzle Temperature [%.1f °C]" { channel="bambulab:printer:myprinter:nozzle-temperature" }
116+
Number:Temperature BedTemperature "Bed Temperature [%.1f °C]" { channel="bambulab:printer:myprinter:bed-temperature" }
117+
String PrintStage "Print Stage [%s]" { channel="bambulab:printer:myprinter:mc-print-stage" }
118+
Switch LedChamber "Chamber LED" { channel="bambulab:printer:myprinter:led-chamber" }
119+
```
120+
121+
## Actions
122+
123+
The printer thing supports actions:
124+
125+
```java
126+
rule "test"
127+
when
128+
/* when */
129+
then
130+
val actions = getActions("bambulab", "bambulab:printer:as8af03m38")
131+
if(actions !==null){
132+
// Refresh all channels
133+
actions.refreshChannels()
134+
actions.sendCommand("Pushing:1:1")
135+
}
136+
end
137+
```
138+
139+
### `refreshChannels`
140+
141+
Reports the complete status of the printer.
142+
This is unnecessary for the X1 series since it already transmits the full object each time.
143+
However, the P1 series only sends the values that have been updated compared to the previous report.
144+
As a rule of thumb, refrain from executing this command at intervals less than 5 minutes on the P1P, as it may cause lag due to its hardware limitations.
145+
146+
### `sendCommand`
147+
148+
The `sendCommand` method expects a string command in the format:
149+
150+
```
151+
CommandType:Parameter1:Parameter2:...
152+
```
153+
154+
#### Possible Commands:
155+
156+
| Command Type | Parameters | Description |
157+
|----------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|
158+
| `Pushing` | `version(int)`,`pushTarget(int)` (optional) | Sends a push command. |
159+
| `Print` | `START` / `STOP` / `PAUSE` | Controls the print job. |
160+
| `ChangeFilament` | `target(int)`,`currentTemperature(int))`,`targetTemperature(int)` | Changes filament using. |
161+
| `AmsUserSetting` | `amsId(int)`,`startupReadOption(boolean)`,`trayReadOption(boolean)` | Sets AMS user settings. |
162+
| `AmsFilamentSetting` | `amsId(int)`,`trayId(int)`,`trayInfoIdx(string)`,`trayColor(string)`,`nozzleTempMin(int)`,`nozzleTempMax(int)`,`trayType(string)` | Configures filament settings. |
163+
| `AmsControl` | ` RESUME` / `RESET` / `PAUSE` | Sends an AMS control command. |
164+
| `PrintSpeed` | `SILENT` / `STANDARD` / `SPORT` / `LUDICROUS` | Adjusts print speed. |
165+
| `GCodeFile` | `filename(string)` | Loads a G-code file. |
166+
| `GCodeLine` | `userId(string)\nlines(string...)` | Sends multiple G-code lines. Lines are enter (`\n`) separated |
167+
| `LedControl` | (`CHAMBER_LIGHT` / `WORK_LIGHT`),(`ON` / `OFF` / `FLASHING`),`ledOnTime(int)?`,`ledOffTime(int)?`,`loopTimes(int)?`,`intervalTime(int)?` | Controls LED lighting. |
168+
| `System` | `GET_ACCESS_CODE` | Executes a system command. |
169+
| `IpCamRecord` | `enable(boolean)` | Starts or stops IP camera recording. |
170+
| `Info` | `GET_VERSION` | Sends a info command. |
171+
| `IpCamTimelaps` | `enable(boolean)` | Enables or disables timelapse recording. |
172+
| `XCamControl` | (`FIRST_LAYER_INSPECTOR` / `SPAGHETTI_DETECTOR`),`control(boolean)`,`printHalt(boolean)` | Controls XCam settings. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.openhab.addons.bundles</groupId>
9+
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
10+
<version>5.0.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>org.openhab.binding.bambulab</artifactId>
14+
15+
<name>openHAB Add-ons :: Bundles :: BambuLab Binding</name>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>pl.grzeslowski</groupId>
20+
<artifactId>JBambuAPI</artifactId>
21+
<version>1.0.0</version>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.eclipse.paho</groupId>
25+
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
26+
<version>1.2.5</version>
27+
</dependency>
28+
<dependency>
29+
<groupId>com.fasterxml.jackson.core</groupId>
30+
<artifactId>jackson-databind</artifactId>
31+
<version>2.18.2</version>
32+
</dependency>
33+
<dependency>
34+
<groupId>org.slf4j</groupId>
35+
<artifactId>slf4j-api</artifactId>
36+
<version>2.0.16</version>
37+
</dependency>
38+
39+
<!-- TEST -->
40+
<dependency>
41+
<groupId>org.assertj</groupId>
42+
<artifactId>assertj-core</artifactId>
43+
<version>3.25.3</version>
44+
<scope>test</scope>
45+
</dependency>
46+
<dependency>
47+
<groupId>org.mockito</groupId>
48+
<artifactId>mockito-core</artifactId>
49+
<version>5.11.0</version>
50+
<scope>test</scope>
51+
</dependency>
52+
</dependencies>
53+
54+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<features name="org.openhab.binding.bambulab-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
3+
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
4+
5+
<feature name="openhab-binding-bambulab" description="BambuLab Binding" version="${project.version}">
6+
<feature>openhab-runtime-base</feature>
7+
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bambulab/${project.version}</bundle>
8+
</feature>
9+
</features>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright (c) 2010-2025 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.bambulab.internal;
14+
15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
import org.openhab.core.thing.ThingTypeUID;
17+
18+
/**
19+
* The {@link BambuLabBindingConstants} class defines common constants, which are
20+
* used across the whole binding.
21+
*
22+
* @author Martin Grześlowski - Initial contribution
23+
*/
24+
@NonNullByDefault
25+
public class BambuLabBindingConstants {
26+
27+
public static final String BINDING_ID = "bambulab";
28+
29+
// List of all Thing Type UIDs
30+
public static final ThingTypeUID PRINTER_THING_TYPE = new ThingTypeUID(BINDING_ID, "printer");
31+
32+
@SuppressWarnings("StaticMethodOnlyUsedInOneClass")
33+
public enum Channel {
34+
CHANNEL_NOZZLE_TEMPERATURE("nozzle-temperature"),
35+
CHANNEL_NOZZLE_TARGET_TEMPERATURE("nozzle-target-temperature"),
36+
CHANNEL_BED_TEMPERATURE("bed-temperature"),
37+
CHANNEL_BED_TARGET_TEMPERATURE("bed-target-temperature"),
38+
CHANNEL_CHAMBER_TEMPERATURE("chamber-temperature"),
39+
CHANNEL_MC_PRINT_STAGE("mc-print-stage"),
40+
CHANNEL_MC_PERCENT("mc-percent"),
41+
CHANNEL_MC_REMAINING_TIME("mc-remaining-time"),
42+
CHANNEL_WIFI_SIGNAL("wifi-signal"),
43+
CHANNEL_BED_TYPE("bed-type"),
44+
CHANNEL_GCODE_FILE("gcode-file"),
45+
CHANNEL_GCODE_STATE("gcode-state"),
46+
CHANNEL_REASON("reason"),
47+
CHANNEL_RESULT("result"),
48+
CHANNEL_GCODE_FILE_PREPARE_PERCENT("gcode-file-prepare-percent"),
49+
CHANNEL_BIG_FAN_1_SPEED("big-fan1-speed"),
50+
CHANNEL_BIG_FAN_2_SPEED("big-fan2-speed"),
51+
CHANNEL_HEAT_BREAK_FAN_SPEED("heat-break-fan-speed"),
52+
CHANNEL_LAYER_NUM("layer-num"),
53+
CHANNEL_SPEED_LEVEL("speed-level"),
54+
CHANNEL_TIME_LAPS("time-laps"),
55+
CHANNEL_USE_AMS("use-ams"),
56+
CHANNEL_VIBRATION_CALIBRATION("vibration-calibration"),
57+
CHANNEL_LED_CHAMBER_LIGHT("led-chamber", true),
58+
CHANNEL_LED_WORK_LIGHT("led-work", true);
59+
60+
private final String name;
61+
private final boolean supportCommand;
62+
63+
Channel(String name, boolean supportCommand) {
64+
this.name = name;
65+
this.supportCommand = supportCommand;
66+
}
67+
68+
private Channel(String name) {
69+
this(name, false);
70+
}
71+
72+
public String getName() {
73+
return name;
74+
}
75+
76+
public boolean isSupportCommand() {
77+
return supportCommand;
78+
}
79+
80+
@Override
81+
public String toString() {
82+
return name;
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)