[bambulab] Support commands for CHANNEL_GCODE_FILE and CHANNEL_SPEED_LEVEL (#18422)

* new commands

Signed-off-by: Martin Grześlowski <martin.grzeslowski@gmail.com>
This commit is contained in:
Martin
2025-03-23 12:05:14 +01:00
committed by GitHub
parent bd611e12d7
commit 805dcac93a
6 changed files with 112 additions and 19 deletions
@@ -13,6 +13,7 @@
package org.openhab.binding.bambulab.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingTypeUID;
/**
@@ -41,7 +42,7 @@ public class BambuLabBindingConstants {
CHANNEL_MC_REMAINING_TIME("mc-remaining-time"),
CHANNEL_WIFI_SIGNAL("wifi-signal"),
CHANNEL_BED_TYPE("bed-type"),
CHANNEL_GCODE_FILE("gcode-file"),
CHANNEL_GCODE_FILE("gcode-file", true),
CHANNEL_GCODE_STATE("gcode-state"),
CHANNEL_REASON("reason"),
CHANNEL_RESULT("result"),
@@ -50,7 +51,7 @@ public class BambuLabBindingConstants {
CHANNEL_BIG_FAN_2_SPEED("big-fan2-speed"),
CHANNEL_HEAT_BREAK_FAN_SPEED("heat-break-fan-speed"),
CHANNEL_LAYER_NUM("layer-num"),
CHANNEL_SPEED_LEVEL("speed-level"),
CHANNEL_SPEED_LEVEL("speed-level", true),
CHANNEL_TIME_LAPS("time-laps"),
CHANNEL_USE_AMS("use-ams"),
CHANNEL_VIBRATION_CALIBRATION("vibration-calibration"),
@@ -81,5 +82,9 @@ public class BambuLabBindingConstants {
public String toString() {
return name;
}
public boolean is(ChannelUID channelUID) {
return name.equals(channelUID.getId());
}
}
}
@@ -48,6 +48,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.grzeslowski.jbambuapi.PrinterClient;
import pl.grzeslowski.jbambuapi.PrinterClient.Channel.GCodeFileCommand;
import pl.grzeslowski.jbambuapi.PrinterClient.Channel.PrintSpeedCommand;
import pl.grzeslowski.jbambuapi.PrinterClientConfig;
import pl.grzeslowski.jbambuapi.PrinterWatcher;
import pl.grzeslowski.jbambuapi.Report;
@@ -71,13 +73,17 @@ public class PrinterHandler extends BaseThingHandler implements PrinterWatcher.S
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (!CHANNEL_LED_CHAMBER_LIGHT.getName().equals(channelUID.getId())
&& !CHANNEL_LED_WORK_LIGHT.getName().equals(channelUID.getId())) {
return;
if (CHANNEL_LED_CHAMBER_LIGHT.is(channelUID) || CHANNEL_LED_WORK_LIGHT.is(channelUID)) {
var ledNode = CHANNEL_LED_CHAMBER_LIGHT.getName().equals(channelUID.getId()) ? CHAMBER_LIGHT : WORK_LIGHT;
var bambuCommand = "ON".equals(command.toFullString()) ? on(ledNode) : off(ledNode);
sendCommand(bambuCommand);
} else if (CHANNEL_GCODE_FILE.is(channelUID)) {
var bambuCommand = new GCodeFileCommand(command.toString());
sendCommand(bambuCommand);
} else if (CHANNEL_SPEED_LEVEL.is(channelUID)) {
var bambuCommand = PrintSpeedCommand.valueOf(command.toString());
sendCommand(bambuCommand);
}
var ledNode = CHANNEL_LED_CHAMBER_LIGHT.getName().equals(channelUID.getId()) ? CHAMBER_LIGHT : WORK_LIGHT;
var bambuCommand = "ON".equals(command.toFullString()) ? on(ledNode) : off(ledNode);
sendCommand(bambuCommand);
}
@Override
@@ -209,7 +215,10 @@ public class PrinterHandler extends BaseThingHandler implements PrinterWatcher.S
updateDecimalState(CHANNEL_BIG_FAN_2_SPEED.getName(), print.bigFan2Speed());
updateDecimalState(CHANNEL_HEAT_BREAK_FAN_SPEED.getName(), print.heatbreakFanSpeed());
updateDecimalState(CHANNEL_LAYER_NUM.getName(), print.layerNum());
updateDecimalState(CHANNEL_SPEED_LEVEL.getName(), print.spdLvl());
if (print.spdLvl() != null) {
var speedLevel = PrintSpeedCommand.findByLevel(print.spdLvl());
updateState(CHANNEL_SPEED_LEVEL.getName(), new StringType(speedLevel.toString()));
}
// boolean
updateBooleanState(CHANNEL_TIME_LAPS.getName(), print.timelapse());
updateBooleanState(CHANNEL_USE_AMS.getName(), print.useAms());
@@ -47,8 +47,6 @@ thing-type.bambulab.printer.channel.reason.label = Pause/Stop Reason
thing-type.bambulab.printer.channel.reason.description = Reason for pausing or stopping the print.
thing-type.bambulab.printer.channel.result.label = Print Result
thing-type.bambulab.printer.channel.result.description = Final result or status of the print job.
thing-type.bambulab.printer.channel.speed-level.label = Print Speed Level
thing-type.bambulab.printer.channel.speed-level.description = Current speed setting of the print job.
thing-type.bambulab.printer.channel.time-laps.label = time-lapse Enabled
thing-type.bambulab.printer.channel.time-laps.description = Indicates whether time-lapse recording is enabled.
thing-type.bambulab.printer.channel.use-ams.label = AMS System in Use
@@ -83,12 +81,28 @@ channel-type.bambulab.on-off-command.state.option.OFF = OFF
channel-type.bambulab.on-off-command.command.option.ON = ON
channel-type.bambulab.on-off-command.command.option.OFF = OFF
channel-type.bambulab.percent.label = Percent Channel
channel-type.bambulab.speed-level.label = Print Speed Level
channel-type.bambulab.speed-level.description = Current speed setting of the print job.
channel-type.bambulab.speed-level.state.option.SILENT = Silent
channel-type.bambulab.speed-level.state.option.STANDARD = Standard
channel-type.bambulab.speed-level.state.option.SPORT = Sport
channel-type.bambulab.speed-level.state.option.LUDICROUS = Ludicrous
channel-type.bambulab.speed-level.command.option.SILENT = Silent
channel-type.bambulab.speed-level.command.option.STANDARD = Standard
channel-type.bambulab.speed-level.command.option.SPORT = Sport
channel-type.bambulab.speed-level.command.option.LUDICROUS = Ludicrous
channel-type.bambulab.string-rw.label = RW String Channel
channel-type.bambulab.string.label = String Channel
channel-type.bambulab.temperature-measurement.label = Current Temperature
channel-type.bambulab.temperature-setpoint.label = Target Temperature
channel-type.bambulab.wifi.label = Wi-Fi Signal Strength
channel-type.bambulab.wifi.description = Current Wi-Fi signal strength.
# thing types
thing-type.bambulab.printer.channel.speed-level.label = Print Speed Level
thing-type.bambulab.printer.channel.speed-level.description = Current speed setting of the print job.
# channel types
channel-type.bambulab.temperature.label = Temperature
@@ -28,6 +28,10 @@
<label>String Channel</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="string-rw">
<item-type>String</item-type>
<label>RW String Channel</label>
</channel-type>
<channel-type id="wifi">
<item-type unitHint="dBm">Number:Power</item-type>
<label>Wi-Fi Signal Strength</label>
@@ -50,6 +54,28 @@
<state readOnly="true"/>
</channel-type>
<channel-type id="speed-level">
<item-type>String</item-type>
<label>Print Speed Level</label>
<description>Current speed setting of the print job.</description>
<state>
<options>
<option value="SILENT">Silent</option>
<option value="STANDARD">Standard</option>
<option value="SPORT">Sport</option>
<option value="LUDICROUS">Ludicrous</option>
</options>
</state>
<command>
<options>
<option value="SILENT">Silent</option>
<option value="STANDARD">Standard</option>
<option value="SPORT">Sport</option>
<option value="LUDICROUS">Ludicrous</option>
</options>
</command>
</channel-type>
<channel-type id="on-off-command">
<item-type>String</item-type>
<label>ON/OFF Channel</label>
@@ -49,7 +49,7 @@
<label>Bed Type</label>
<description>Type of the printer's heated bed.</description>
</channel>
<channel id="gcode-file" typeId="string">
<channel id="gcode-file" typeId="string-rw">
<label>G-code File</label>
<description>Name of the currently loaded G-code file.</description>
</channel>
@@ -85,10 +85,7 @@
<label>Current Layer Number</label>
<description>Current layer being printed.</description>
</channel>
<channel id="speed-level" typeId="number">
<label>Print Speed Level</label>
<description>Current speed setting of the print job.</description>
</channel>
<channel id="speed-level" typeId="speed-level"/>
<channel id="time-laps" typeId="boolean">
<label>time-lapse Enabled</label>
<description>Indicates whether time-lapse recording is enabled.</description>
@@ -22,17 +22,23 @@ import static pl.grzeslowski.jbambuapi.PrinterClient.Channel.LedControlCommand.L
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openhab.binding.bambulab.internal.BambuLabBindingConstants.Channel;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import pl.grzeslowski.jbambuapi.PrinterClient;
import pl.grzeslowski.jbambuapi.PrinterClient.Channel.PrintSpeedCommand;
/**
* @author Martin Grześlowski - Initial contribution
@@ -40,13 +46,19 @@ import pl.grzeslowski.jbambuapi.PrinterClient;
@ExtendWith(MockitoExtension.class)
@NonNullByDefault
class PrinterHandlerTest {
@Spy
PrinterHandler printerHandler = new PrinterHandler(mock(Thing.class));
@BeforeEach
void setUp() {
lenient().doNothing().when(printerHandler).sendCommand(any(PrinterClient.Channel.Command.class));
}
@ParameterizedTest(name = "Should handle {0} command for {1} channel and send {2}")
@MethodSource
public void testSendLightCommand(OnOffType command, Channel channel, PrinterClient.Channel.Command sendCommand) {
// Given
var printerHandler = spy(new PrinterHandler(mock(Thing.class)));
var channelUID = new ChannelUID("bambulab:printer:test:" + channel);
doNothing().when(printerHandler).sendCommand(any(PrinterClient.Channel.Command.class));
// When
printerHandler.handleCommand(channelUID, command);
@@ -63,11 +75,41 @@ class PrinterHandlerTest {
Arguments.of(OnOffType.OFF, CHANNEL_LED_WORK_LIGHT, off(WORK_LIGHT)));
}
@Test
@DisplayName("should send gcode command to a printer when command to CHANNEL_GCODE_FILE is sent")
void testGCode() {
// given
var channelUID = new ChannelUID("bambulab:printer:test:" + CHANNEL_GCODE_FILE.getName());
// when
printerHandler.handleCommand(channelUID, new StringType("gcode-file"));
// then
verify(printerHandler).sendCommand(eq(new PrinterClient.Channel.GCodeFileCommand("gcode-file")));
}
@ParameterizedTest(name = "{index}: should accept StringType(\"{0}\") and send {1} command to a printer")
@MethodSource
void speedLevel(String speedLevel, PrintSpeedCommand command) {
// given
var channelUID = new ChannelUID("bambulab:printer:test:" + CHANNEL_SPEED_LEVEL.getName());
// when
printerHandler.handleCommand(channelUID, new StringType(speedLevel));
// then
verify(printerHandler).sendCommand(eq(command));
}
static Stream<Arguments> speedLevel() {
return stream(PrintSpeedCommand.values())//
.map(command -> Arguments.of(command.name(), command));
}
@ParameterizedTest(name = "Command to channel {0} should not invoke `client.sendCommand`")
@MethodSource
public void notImplementedCommands(Channel channel) {
// Given
var printerHandler = spy(new PrinterHandler(mock(Thing.class)));
var channelUID = new ChannelUID("bambulab:printer:test:" + channel);
// When