diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java index e2d37a7b506..6a521fbe547 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/PercentageValue.java @@ -54,9 +54,10 @@ public class PercentageValue extends Value { private final BigDecimal stepPercent; private final @Nullable String onValue; private final @Nullable String offValue; + private final @Nullable String formatOverride; public PercentageValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step, - @Nullable String onValue, @Nullable String offValue) { + @Nullable String onValue, @Nullable String offValue, @Nullable String formatOverride) { super(CoreItemFactory.DIMMER, List.of(DecimalType.class, QuantityType.class, IncreaseDecreaseType.class, OnOffType.class, UpDownType.class, StringType.class)); this.onValue = onValue; @@ -69,6 +70,7 @@ public class PercentageValue extends Value { this.span = this.max.subtract(this.min); this.step = step == null ? BigDecimal.ONE : step; this.stepPercent = this.step.multiply(HUNDRED).divide(this.span, MathContext.DECIMAL128); + this.formatOverride = formatOverride; } @Override @@ -135,7 +137,10 @@ public class PercentageValue extends Value { @Override public String getMQTTpublishValue(Command command, @Nullable String pattern) { - String formatPattern = pattern; + String formatPattern = this.formatOverride; + if (formatPattern == null) { + formatPattern = pattern; + } if (formatPattern == null) { formatPattern = "%s"; } @@ -170,7 +175,7 @@ public class PercentageValue extends Value { @Override public StateDescriptionFragmentBuilder createStateDescription(boolean readOnly) { - return super.createStateDescription(readOnly).withMaximum(HUNDRED).withMinimum(BigDecimal.ZERO).withStep(step) - .withPattern("%.0f %%"); + return super.createStateDescription(readOnly).withMaximum(HUNDRED).withMinimum(BigDecimal.ZERO) + .withStep(stepPercent).withPattern("%.0f %%"); } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java index 2a361d84276..32b2826e9ea 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java @@ -54,7 +54,7 @@ public class ValueFactory { value = new NumberValue(config.min, config.max, config.step, UnitUtils.parseUnit(config.unit)); break; case MqttBindingConstants.DIMMER: - value = new PercentageValue(config.min, config.max, config.step, config.on, config.off); + value = new PercentageValue(config.min, config.max, config.step, config.on, config.off, null); break; case MqttBindingConstants.COLOR_HSB: value = new ColorValue(ColorMode.HSB, config.on, config.off, config.onBrightness); diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java index 2fe0a9f6112..5f960f691d0 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/ChannelStateTests.java @@ -267,7 +267,7 @@ public class ChannelStateTests { @Test public void receivePercentageTest() { PercentageValue value = new PercentageValue(new BigDecimal(-100), new BigDecimal(100), new BigDecimal(10), null, - null); + null, null); ChannelState c = spy(new ChannelState(config, channelUIDMock, value, channelStateUpdateListenerMock)); c.start(connectionMock, mock(ScheduledExecutorService.class), 100); diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java index dd95a8e784b..b602e16897c 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.*; import java.math.BigDecimal; +import java.math.MathContext; import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -99,7 +100,7 @@ public class ValueTests { @Test public void illegalPercentCommand() { - PercentageValue v = new PercentageValue(null, null, null, null, null); + PercentageValue v = new PercentageValue(null, null, null, null, null, null); assertThrows(IllegalStateException.class, () -> v.parseCommand(new StringType("demo"))); } @@ -111,7 +112,7 @@ public class ValueTests { @Test public void illegalPercentUpdate() { - PercentageValue v = new PercentageValue(null, null, null, null, null); + PercentageValue v = new PercentageValue(null, null, null, null, null, null); assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(101.0))); } @@ -304,7 +305,9 @@ public class ValueTests { @Test public void percentCalc() { PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null, - null); + null, null); + assertThat(v.createStateDescription(false).build().getStep(), is(new BigDecimal(1))); + assertThat(v.parseCommand(new DecimalType("110.0")), is(PercentType.HUNDRED)); assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("110")); assertThat(v.parseCommand(new DecimalType(10.0)), is(PercentType.ZERO)); @@ -316,9 +319,20 @@ public class ValueTests { assertThat(v.getMQTTpublishValue(OnOffType.OFF, null), is("10")); } + @Test + public void percentFormatOverride() { + PercentageValue v = new PercentageValue(BigDecimal.ZERO, new BigDecimal(3.0), null, null, null, "%.0f"); + assertThat(v.createStateDescription(false).build().getStep(), + is(new BigDecimal(100).divide(new BigDecimal(3), MathContext.DECIMAL128))); + assertThat(v.getMQTTpublishValue(PercentType.HUNDRED, null), is("3")); + assertThat(v.getMQTTpublishValue(PercentType.valueOf("67"), null), is("2")); + assertThat(v.getMQTTpublishValue(PercentType.valueOf("33"), null), is("1")); + assertThat(v.getMQTTpublishValue(PercentType.ZERO, null), is("0")); + } + @Test public void percentMQTTValue() { - PercentageValue v = new PercentageValue(null, null, null, null, null); + PercentageValue v = new PercentageValue(null, null, null, null, null, null); assertThat(v.parseCommand(new DecimalType("10.10000")), is(new PercentType("10.1"))); assertThat(v.getMQTTpublishValue(new PercentType("10.1"), null), is("10.1")); Command command; @@ -333,7 +347,7 @@ public class ValueTests { @Test public void percentCustomOnOff() { PercentageValue v = new PercentageValue(new BigDecimal("0.0"), new BigDecimal("100.0"), new BigDecimal("1.0"), - "on", "off"); + "on", "off", null); assertThat(v.parseCommand(new StringType("on")), is(OnOffType.ON)); assertThat(v.getMQTTpublishValue(OnOffType.ON, "%s"), is("on")); assertThat(v.parseCommand(new StringType("off")), is(OnOffType.OFF)); @@ -343,7 +357,7 @@ public class ValueTests { @Test public void decimalCalc() { PercentageValue v = new PercentageValue(new BigDecimal("0.1"), new BigDecimal("1.0"), new BigDecimal("0.1"), - null, null); + null, null, null); assertThat(v.parseCommand(new DecimalType(1.0)), is(PercentType.HUNDRED)); assertThat(v.parseCommand(new DecimalType(0.1)), is(PercentType.ZERO)); PercentType command = (PercentType) v.parseCommand(new DecimalType(0.2)); @@ -353,7 +367,7 @@ public class ValueTests { @Test public void increaseDecreaseCalc() { PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"), - null, null); + null, null, null); // Normal operation. PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0")); @@ -382,7 +396,7 @@ public class ValueTests { @Test public void upDownCalc() { PercentageValue v = new PercentageValue(new BigDecimal("1.0"), new BigDecimal("11.0"), new BigDecimal("0.5"), - null, null); + null, null, null); // Normal operation. PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0")); @@ -411,7 +425,7 @@ public class ValueTests { @Test public void percentCalcInvalid() { PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), null, - null); + null, null); assertThrows(IllegalArgumentException.class, () -> v.parseCommand(new DecimalType(9.0))); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java index 8f5132b79e6..99394e08860 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Fan.java @@ -50,6 +50,9 @@ public class Fan extends AbstractComponent implements public static final String OSCILLATION_CHANNEL_ID = "oscillation"; public static final String DIRECTION_CHANNEL_ID = "direction"; + private static final BigDecimal BIG_DECIMAL_HUNDRED = new BigDecimal(100); + private static final String FORMAT_INTEGER = "%.0f"; + /** * Configuration class for MQTT component */ @@ -60,6 +63,8 @@ public class Fan extends AbstractComponent implements protected @Nullable Boolean optimistic; + @SerializedName("state_value_template") + protected @Nullable String stateValueTemplate; @SerializedName("state_topic") protected @Nullable String stateTopic; @SerializedName("command_template") @@ -136,7 +141,7 @@ public class Fan extends AbstractComponent implements : this; onOffChannel = buildChannel(newStyleChannels ? SWITCH_CHANNEL_ID : SWITCH_CHANNEL_ID_DEPRECATED, ComponentChannelType.SWITCH, onOffValue, "On/Off State", onOffListener) - .stateTopic(channelConfiguration.stateTopic, channelConfiguration.getValueTemplate()) + .stateTopic(channelConfiguration.stateTopic, channelConfiguration.stateValueTemplate) .commandTopic(channelConfiguration.commandTopic, channelConfiguration.isRetain(), channelConfiguration.getQos(), channelConfiguration.commandTemplate) .inferOptimistic(channelConfiguration.optimistic) @@ -144,10 +149,9 @@ public class Fan extends AbstractComponent implements rawSpeedState = UnDefType.NULL; - int speeds = Math.min(channelConfiguration.speedRangeMax, 100) - Math.max(channelConfiguration.speedRangeMin, 1) - + 1; - speedValue = new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.valueOf(100.0d / speeds), - channelConfiguration.payloadOn, channelConfiguration.payloadOff); + speedValue = new PercentageValue(BigDecimal.valueOf(channelConfiguration.speedRangeMin - 1), + BigDecimal.valueOf(channelConfiguration.speedRangeMax), null, channelConfiguration.payloadOn, + channelConfiguration.payloadOff, FORMAT_INTEGER); if (channelConfiguration.percentageCommandTopic != null) { hiddenChannels.add(onOffChannel); diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java index 443d06797f9..d704679adef 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Light.java @@ -73,6 +73,8 @@ public abstract class Light extends AbstractComponent effectList = channelConfiguration.effectList; if (effectList != null) { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java index 8a1abfe2418..e1d1035a264 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/TemplateSchemaLight.java @@ -84,7 +84,7 @@ public class TemplateSchemaLight extends AbstractRawSchemaLight { } onOffValue = new OnOffValue("on", "off"); - brightnessValue = new PercentageValue(null, new BigDecimal(255), null, null, null); + brightnessValue = new PercentageValue(null, new BigDecimal(255), null, null, null, FORMAT_INTEGER); if (channelConfiguration.redTemplate != null && channelConfiguration.greenTemplate != null && channelConfiguration.blueTemplate != null) { diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java index f7cdde2ba07..502601c0e00 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Vacuum.java @@ -173,7 +173,7 @@ public class Vacuum extends AbstractComponent { if (supportedFeatures.contains(FEATURE_BATTERY)) { buildOptionalChannel(newStyleChannels ? BATTERY_LEVEL_CH_ID : BATTERY_LEVEL_CH_ID_DEPRECATED, ComponentChannelType.DIMMER, - new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.ONE, null, null), + new PercentageValue(BigDecimal.ZERO, BigDecimal.valueOf(100), BigDecimal.ONE, null, null, null), updateListener, null, null, "{{ value_json.battery_level }}", channelConfiguration.stateTopic); } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Valve.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Valve.java index 6c5f8e54f27..5a0cc23cf73 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Valve.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/component/Valve.java @@ -61,6 +61,8 @@ public class Valve extends AbstractComponent impleme private static final String POSITION_KEY = "position"; private static final String STATE_KEY = "state"; + private static final String FORMAT_INTEGER = "%.0f"; + private final Logger logger = LoggerFactory.getLogger(Valve.class); /** @@ -121,7 +123,7 @@ public class Valve extends AbstractComponent impleme onOffValue = new OnOffValue(channelConfiguration.stateOpen, channelConfiguration.stateClosed, channelConfiguration.payloadOpen, channelConfiguration.payloadClose); positionValue = new PercentageValue(BigDecimal.valueOf(channelConfiguration.positionClosed), - BigDecimal.valueOf(channelConfiguration.positionOpen), null, null, null); + BigDecimal.valueOf(channelConfiguration.positionOpen), null, null, null, FORMAT_INTEGER); if (channelConfiguration.reportsPosition) { buildChannel(VALVE_CHANNEL_ID, ComponentChannelType.DIMMER, positionValue, getName(), this) diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java index 7869752548a..7978ff0d137 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/FanTests.java @@ -16,6 +16,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import java.math.BigDecimal; +import java.math.MathContext; import java.util.Objects; import java.util.Set; @@ -90,6 +91,70 @@ public class FanTests extends AbstractComponentTests { assertPublished("zigbee2mqtt/fan/set/state", "ON_"); } + @SuppressWarnings("null") + @Test + public void testPercentageWithTemplates() throws InterruptedException { + var component = discoverComponent(configTopicToMqtt(CONFIG_TOPIC), + """ + { + "availability": [ + { + "topic": "zigbee2mqtt/bridge/state" + } + ], + "device": { + "identifiers": [ + "zigbee2mqtt_0x0000000000000000" + ], + "manufacturer": "Fans inc", + "model": "Fan", + "name": "FanBlower", + "sw_version": "Zigbee2MQTT 1.18.2" + }, + "name": "fan", + "state_topic": "zigbee2mqtt/fan", + "state_value_template": "{{ value_json.fan_state }}", + "command_topic": "zigbee2mqtt/fan/set/fan_state", + "percentage_command_template": "{{ {0:'off', 1:'low', 2:'medium', 3:'high'}[value] | default('') }}", + "percentage_command_topic": "zigbee2mqtt/fan/set/fan_mode", + "percentage_state_topic": "zigbee2mqtt/fan", + "percentage_value_template": "{{ {'off':0, 'low':1, 'medium':2, 'high':3}[value_json.fan_mode] | default('None') }}", + "speed_range_max": 3, + "speed_range_min": 1 + } + """); + + assertThat(component.channels.size(), is(1)); + assertThat(component.getName(), is("fan")); + + assertChannel(component, Fan.SPEED_CHANNEL_ID, "zigbee2mqtt/fan", "zigbee2mqtt/fan/set/fan_mode", "Speed", + PercentageValue.class, null); + + publishMessage("zigbee2mqtt/fan", "{ \"fan_state\": \"OFF\", \"fan_mode\": \"high\"}"); + assertState(component, Fan.SPEED_CHANNEL_ID, PercentType.ZERO); + publishMessage("zigbee2mqtt/fan", "{ \"fan_state\": \"ON\", \"fan_mode\": \"high\"}"); + assertState(component, Fan.SPEED_CHANNEL_ID, PercentType.HUNDRED); + publishMessage("zigbee2mqtt/fan", "{ \"fan_state\": \"ON\", \"fan_mode\": \"medium\"}"); + assertState(component, Fan.SPEED_CHANNEL_ID, + new PercentType(new BigDecimal(200).divide(new BigDecimal(3), MathContext.DECIMAL128))); + publishMessage("zigbee2mqtt/fan", "{ \"fan_state\": \"ON\", \"fan_mode\": \"low\"}"); + assertState(component, Fan.SPEED_CHANNEL_ID, + new PercentType(new BigDecimal(100).divide(new BigDecimal(3), MathContext.DECIMAL128))); + + component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(OnOffType.OFF); + assertPublished("zigbee2mqtt/fan/set/fan_state", "OFF"); + component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(OnOffType.ON); + assertPublished("zigbee2mqtt/fan/set/fan_state", "ON"); + component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(PercentType.HUNDRED); + assertPublished("zigbee2mqtt/fan/set/fan_mode", "high"); + component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(PercentType.ZERO); + assertPublished("zigbee2mqtt/fan/set/fan_mode", "off"); + component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(new PercentType(33)); + assertPublished("zigbee2mqtt/fan/set/fan_mode", "low"); + component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(new PercentType(66)); + assertPublished("zigbee2mqtt/fan/set/fan_mode", "medium"); + } + @SuppressWarnings("null") @Test public void testInferredOptimistic() throws InterruptedException { @@ -287,7 +352,7 @@ public class FanTests extends AbstractComponentTests { assertChannel(component, Fan.SPEED_CHANNEL_ID, "bedroom_fan/speed/percentage_state", "bedroom_fan/speed/percentage", "Speed", PercentageValue.class); var channel = Objects.requireNonNull(component.getChannel(Fan.SPEED_CHANNEL_ID)); - assertThat(channel.getStateDescription().getStep(), is(BigDecimal.valueOf(10.0d))); + assertThat(channel.getStateDescription().getStep(), is(BigDecimal.valueOf(10))); assertChannel(component, Fan.OSCILLATION_CHANNEL_ID, "bedroom_fan/oscillation/state", "bedroom_fan/oscillation/set", "Oscillation", OnOffValue.class); assertChannel(component, Fan.DIRECTION_CHANNEL_ID, "bedroom_fan/direction/state", "bedroom_fan/direction/set", @@ -300,16 +365,16 @@ public class FanTests extends AbstractComponentTests { publishMessage("bedroom_fan/on/state", "false"); assertState(component, Fan.SPEED_CHANNEL_ID, PercentType.ZERO); publishMessage("bedroom_fan/on/state", "true"); - publishMessage("bedroom_fan/speed/percentage_state", "50"); + publishMessage("bedroom_fan/speed/percentage_state", "5"); assertState(component, Fan.SPEED_CHANNEL_ID, new PercentType(50)); publishMessage("bedroom_fan/on/state", "false"); // Off, even though we got an updated speed assertState(component, Fan.SPEED_CHANNEL_ID, PercentType.ZERO); - publishMessage("bedroom_fan/speed/percentage_state", "25"); + publishMessage("bedroom_fan/speed/percentage_state", "2"); assertState(component, Fan.SPEED_CHANNEL_ID, PercentType.ZERO); publishMessage("bedroom_fan/on/state", "true"); // Now that it's on, the channel reflects the proper speed - assertState(component, Fan.SPEED_CHANNEL_ID, new PercentType(25)); + assertState(component, Fan.SPEED_CHANNEL_ID, new PercentType(20)); publishMessage("bedroom_fan/oscillation/state", "true"); assertState(component, Fan.OSCILLATION_CHANNEL_ID, OnOffType.ON); @@ -333,7 +398,7 @@ public class FanTests extends AbstractComponentTests { // Setting to a specific speed turns it on first component.getChannel(Fan.SPEED_CHANNEL_ID).getState().publishValue(PercentType.HUNDRED); assertPublished("bedroom_fan/on/set", "true"); - assertPublished("bedroom_fan/speed/percentage", "100"); + assertPublished("bedroom_fan/speed/percentage", "10"); component.getChannel(Fan.OSCILLATION_CHANNEL_ID).getState().publishValue(OnOffType.ON); assertPublished("bedroom_fan/oscillation/set", "true"); diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java index 3b676dccd55..2ca0342366f 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java @@ -191,7 +191,7 @@ public class Property implements AttributeChanged { step = new BigDecimal(1); } if (attributes.unit.contains("%") && attributes.settable) { - value = new PercentageValue(min, max, step, null, null); + value = new PercentageValue(min, max, step, null, null, null); } else { value = new NumberValue(min, max, step, unit); }