[mqtt.generic] Add optional stopCommandTopic for rollershutters (#17158)
* [mqtt.generic] Add optional stopCommandTopic for rollershutters Signed-off-by: Cody Cutrer <cody@cutrer.us>pull/17185/head
parent
cc6a202034
commit
7baec4d651
|
@ -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.
|
- **on**: An optional string (like "Open") that is recognized as `UP` state.
|
||||||
- **off**: An optional string (like "Close") that is recognized as `DOWN` 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.
|
- **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%.
|
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.
|
If strings are defined for these values, they are used for sending commands to the broker, too.
|
||||||
|
|
|
@ -32,6 +32,7 @@ public class ChannelConfig {
|
||||||
/** This is either a state topic or a trigger topic, depending on {@link #trigger}. */
|
/** This is either a state topic or a trigger topic, depending on {@link #trigger}. */
|
||||||
public String stateTopic = "";
|
public String stateTopic = "";
|
||||||
public String commandTopic = "";
|
public String commandTopic = "";
|
||||||
|
public String stopCommandTopic = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, the channel state is not updated on a new message.
|
* If true, the channel state is not updated on a new message.
|
||||||
|
|
|
@ -59,6 +59,13 @@ public class ChannelConfigBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChannelConfigBuilder withStopCommandTopic(@Nullable String topic) {
|
||||||
|
if (topic != null) {
|
||||||
|
config.stopCommandTopic = topic;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ChannelConfigBuilder withRetain(boolean retain) {
|
public ChannelConfigBuilder withRetain(boolean retain) {
|
||||||
config.retained = retain;
|
config.retained = retain;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
|
||||||
import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
|
import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
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.library.types.StringType;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
|
@ -420,7 +421,13 @@ public class ChannelState implements MqttMessageSubscriber {
|
||||||
|
|
||||||
int qos = (config.qos != null) ? config.qos : connection.getQos();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
<description>An MQTT topic that this thing will send a command to. If not set, this will be a read-only
|
<description>An MQTT topic that this thing will send a command to. If not set, this will be a read-only
|
||||||
rollershutter.</description>
|
rollershutter.</description>
|
||||||
</parameter>
|
</parameter>
|
||||||
|
<parameter name="stopCommandTopic" type="text">
|
||||||
|
<label>MQTT Stop Command Topic</label>
|
||||||
|
<description>An MQTT topic that this thing will send a STOP command to. If not set, it will send STOP commands to the
|
||||||
|
main commandTopic.</description>
|
||||||
|
</parameter>
|
||||||
<parameter name="transformationPattern" type="text" groupName="transformations">
|
<parameter name="transformationPattern" type="text" groupName="transformations">
|
||||||
<label>Incoming Value Transformations</label>
|
<label>Incoming Value Transformations</label>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
|
|
|
@ -156,6 +156,8 @@ thing-type.config.mqtt.rollershutter_channel.stateTopic.label = MQTT State Topic
|
||||||
thing-type.config.mqtt.rollershutter_channel.stateTopic.description = An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
|
thing-type.config.mqtt.rollershutter_channel.stateTopic.description = An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
|
||||||
thing-type.config.mqtt.rollershutter_channel.stop.label = Stop Command
|
thing-type.config.mqtt.rollershutter_channel.stop.label = Stop Command
|
||||||
thing-type.config.mqtt.rollershutter_channel.stop.description = A string (like "STOP") that is sent when commanding the rollershutter to stop.
|
thing-type.config.mqtt.rollershutter_channel.stop.description = A string (like "STOP") that is sent when commanding the rollershutter to stop.
|
||||||
|
thing-type.config.mqtt.rollershutter_channel.stopCommandTopic.label = MQTT Stop Command Topic
|
||||||
|
thing-type.config.mqtt.rollershutter_channel.stopCommandTopic.description = An MQTT topic that this thing will send a STOP command to. If not set, it will send STOP commands to the main commandTopic.
|
||||||
thing-type.config.mqtt.rollershutter_channel.transformExtentsToString.label = Transform Commands at Extents to String
|
thing-type.config.mqtt.rollershutter_channel.transformExtentsToString.label = Transform Commands at Extents to String
|
||||||
thing-type.config.mqtt.rollershutter_channel.transformExtentsToString.description = If a command is 0 or 100, send that as UP or DOWN commands instead. Useful if your device doesn't support going to a specific position - only opening or closing, but you have front ends (say HomeKit) or rules that will only send percentage commands instead of UP/DOWN.
|
thing-type.config.mqtt.rollershutter_channel.transformExtentsToString.description = If a command is 0 or 100, send that as UP or DOWN commands instead. Useful if your device doesn't support going to a specific position - only opening or closing, but you have front ends (say HomeKit) or rules that will only send percentage commands instead of UP/DOWN.
|
||||||
thing-type.config.mqtt.rollershutter_channel.transformationPattern.label = Incoming Value Transformations
|
thing-type.config.mqtt.rollershutter_channel.transformationPattern.label = Incoming Value Transformations
|
||||||
|
|
|
@ -52,6 +52,7 @@ import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
|
||||||
import org.openhab.core.library.types.HSBType;
|
import org.openhab.core.library.types.HSBType;
|
||||||
import org.openhab.core.library.types.PercentType;
|
import org.openhab.core.library.types.PercentType;
|
||||||
import org.openhab.core.library.types.RawType;
|
import org.openhab.core.library.types.RawType;
|
||||||
|
import org.openhab.core.library.types.StopMoveType;
|
||||||
import org.openhab.core.library.types.StringType;
|
import org.openhab.core.library.types.StringType;
|
||||||
import org.openhab.core.library.unit.Units;
|
import org.openhab.core.library.unit.Units;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
@ -134,6 +135,41 @@ public class ChannelStateTests {
|
||||||
verify(connectionMock).unsubscribe(eq("state"), eq(c));
|
verify(connectionMock).unsubscribe(eq("state"), eq(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void publishStopTest() throws Exception {
|
||||||
|
ChannelConfig config = ChannelConfigBuilder.create("state", "command").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("command"), argThat(p -> 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
|
@Test
|
||||||
public void receiveWildcardTest() throws Exception {
|
public void receiveWildcardTest() throws Exception {
|
||||||
ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state/+/topic", "command").build(),
|
ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state/+/topic", "command").build(),
|
||||||
|
|
Loading…
Reference in New Issue