diff --git a/bundles/org.openhab.binding.mqtt.generic/README.md b/bundles/org.openhab.binding.mqtt.generic/README.md
index 46aae9e0eea..8aa4f81913e 100644
--- a/bundles/org.openhab.binding.mqtt.generic/README.md
+++ b/bundles/org.openhab.binding.mqtt.generic/README.md
@@ -199,6 +199,7 @@ The channel expects values on the corresponding MQTT topic to be in this format
- **on**: An optional string (like "Open") that is recognized as `UP` state.
- **off**: An optional string (like "Close") that is recognized as `DOWN` state.
- **stop**: An optional string (like "Stop") that is recognized as `STOP` state.
+- **stopCommandTopic**: An optional topic to send `STOP` commands to. If not set, `STOP` commands are sent to the main **commandTopic**.
Internally `UP` is converted to 0%, `DOWN` to 100%.
If strings are defined for these values, they are used for sending commands to the broker, too.
diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfig.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfig.java
index d3adf267786..b907052019c 100644
--- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfig.java
+++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfig.java
@@ -32,6 +32,7 @@ public class ChannelConfig {
/** This is either a state topic or a trigger topic, depending on {@link #trigger}. */
public String stateTopic = "";
public String commandTopic = "";
+ public String stopCommandTopic = "";
/**
* If true, the channel state is not updated on a new message.
diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfigBuilder.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfigBuilder.java
index 9c4fe483669..8df35ecb57a 100644
--- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfigBuilder.java
+++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelConfigBuilder.java
@@ -59,6 +59,13 @@ public class ChannelConfigBuilder {
return this;
}
+ public ChannelConfigBuilder withStopCommandTopic(@Nullable String topic) {
+ if (topic != null) {
+ config.stopCommandTopic = topic;
+ }
+ return this;
+ }
+
public ChannelConfigBuilder withRetain(boolean retain) {
config.retained = retain;
return this;
diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java
index 832f94397e1..06ea08fbdbc 100644
--- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java
+++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java
@@ -30,6 +30,7 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.types.Command;
@@ -420,7 +421,13 @@ public class ChannelState implements MqttMessageSubscriber {
int qos = (config.qos != null) ? config.qos : connection.getQos();
- return connection.publish(config.commandTopic, commandString.getBytes(), qos, config.retained);
+ String commandTopic;
+ if (command.equals(StopMoveType.STOP) && !config.stopCommandTopic.isEmpty()) {
+ commandTopic = config.stopCommandTopic;
+ } else {
+ commandTopic = config.commandTopic;
+ }
+ return connection.publish(commandTopic, commandString.getBytes(), qos, config.retained);
}
/**
diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/OH-INF/config/rollershutter-channel-config.xml b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/OH-INF/config/rollershutter-channel-config.xml
index b87161d70a3..25f78a194b1 100644
--- a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/OH-INF/config/rollershutter-channel-config.xml
+++ b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/OH-INF/config/rollershutter-channel-config.xml
@@ -22,6 +22,11 @@
An MQTT topic that this thing will send a command to. If not set, this will be a read-only
rollershutter.
+
+
+ An MQTT topic that this thing will send a STOP command to. If not set, it will send STOP commands to the
+ main commandTopic.
+ Arrays.equals(p, "STOP".getBytes())), anyInt(),
+ eq(false));
+
+ c.stop().get();
+ verify(connectionMock).unsubscribe(eq("state"), eq(c));
+ }
+
+ @Test
+ public void publishStopSeparateTopicTest() throws Exception {
+ ChannelConfig config = ChannelConfigBuilder.create("state", "command").withStopCommandTopic("stopCommand")
+ .build();
+ config.stop = "STOP";
+ ChannelState c = spy(new ChannelState(config, channelUIDMock, textValue, channelStateUpdateListenerMock));
+
+ c.start(connectionMock, scheduler, 0).get(50, TimeUnit.MILLISECONDS);
+ verify(connectionMock).subscribe(eq("state"), eq(c));
+
+ c.publishValue(StopMoveType.STOP).get();
+ verify(connectionMock).publish(eq("stopCommand"), argThat(p -> Arrays.equals(p, "STOP".getBytes())), anyInt(),
+ eq(false));
+
+ c.stop().get();
+ verify(connectionMock).unsubscribe(eq("state"), eq(c));
+ }
+
@Test
public void receiveWildcardTest() throws Exception {
ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state/+/topic", "command").build(),