From b079e09b35a51f672f3e00ac99cd6ceced6554f0 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Fri, 14 Jun 2024 19:07:58 +0200 Subject: [PATCH] [MQTT] Fix state description (#16866) * fix state description Signed-off-by: Mark Herwege Signed-off-by: Ciprian Pascu --- .../mqtt/generic/values/DateTimeValue.java | 7 +++ .../mqtt/generic/values/NumberValue.java | 21 ++++---- .../mqtt/generic/values/PercentageValue.java | 2 +- .../mqtt/generic/values/ValueTests.java | 54 ++++++++++--------- .../internal/component/SensorTests.java | 2 +- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java index 96ea93da442..27056e8328b 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/DateTimeValue.java @@ -21,6 +21,7 @@ import org.openhab.core.library.CoreItemFactory; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.StringType; import org.openhab.core.types.Command; +import org.openhab.core.types.StateDescriptionFragmentBuilder; /** * Implements a datetime value. @@ -50,4 +51,10 @@ public class DateTimeValue extends Value { } return String.format(formatPattern, ((DateTimeType) command).getZonedDateTime()); } + + @Override + public StateDescriptionFragmentBuilder createStateDescription(boolean readOnly) { + return StateDescriptionFragmentBuilder.create().withReadOnly(readOnly) + .withPattern("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"); + } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java index 3ae6ee2e427..06afc9b497f 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/NumberValue.java @@ -25,7 +25,6 @@ import org.openhab.core.library.types.IncreaseDecreaseType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.UpDownType; -import org.openhab.core.library.unit.Units; import org.openhab.core.types.Command; import org.openhab.core.types.StateDescriptionFragmentBuilder; import org.openhab.core.types.Type; @@ -53,16 +52,16 @@ public class NumberValue extends Value { private final @Nullable BigDecimal min; private final @Nullable BigDecimal max; private final BigDecimal step; - private final Unit unit; + private final @Nullable Unit unit; public NumberValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step, @Nullable Unit unit) { - super(CoreItemFactory.NUMBER, - List.of(QuantityType.class, IncreaseDecreaseType.class, UpDownType.class, StringType.class)); + super(CoreItemFactory.NUMBER, List.of(DecimalType.class, QuantityType.class, IncreaseDecreaseType.class, + UpDownType.class, StringType.class)); this.min = min; this.max = max; this.step = step == null ? BigDecimal.ONE : step; - this.unit = unit != null ? unit : Units.ONE; + this.unit = unit; } protected boolean checkConditions(BigDecimal newValue) { @@ -116,7 +115,8 @@ public class NumberValue extends Value { } // items with units specified in the label in the UI but no unit on mqtt are stored as // DecimalType to avoid conversions (e.g. % expects 0-1 rather than 0-100) - if (!Units.ONE.equals(unit)) { + Unit unit = this.unit; + if (unit != null) { return new QuantityType<>(newValue, unit); } else { return new DecimalType(newValue); @@ -147,7 +147,8 @@ public class NumberValue extends Value { private BigDecimal getQuantityTypeAsDecimal(QuantityType qType) { BigDecimal val = qType.toBigDecimal(); - if (!qType.getUnit().isCompatible(Units.ONE)) { + Unit unit = this.unit; + if (unit != null) { QuantityType convertedType = qType.toInvertibleUnit(unit); if (convertedType != null) { val = convertedType.toBigDecimal(); @@ -167,10 +168,10 @@ public class NumberValue extends Value { if (min != null) { builder = builder.withMinimum(min); } - if (!unit.equals(Units.ONE)) { - builder.withPattern("%s " + unit); + if (unit != null) { + builder.withPattern("%.0f %unit%"); } else { - builder.withPattern("%s %unit%"); + builder.withPattern("%.0f"); } return builder.withStep(step); } 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 00c4af0ad8e..77643506ce2 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 @@ -152,6 +152,6 @@ public class PercentageValue extends Value { @Override public StateDescriptionFragmentBuilder createStateDescription(boolean readOnly) { return super.createStateDescription(readOnly).withMaximum(HUNDRED).withMinimum(BigDecimal.ZERO).withStep(step) - .withPattern("%s %%"); + .withPattern("%.0f %%"); } } 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 f91c919f567..21a9046b0e0 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 @@ -35,7 +35,6 @@ import org.openhab.core.library.types.UpDownType; import org.openhab.core.library.unit.MetricPrefix; import org.openhab.core.library.unit.Units; import org.openhab.core.types.Command; -import org.openhab.core.types.State; import org.openhab.core.types.TypeParser; import org.openhab.core.types.UnDefType; @@ -70,17 +69,17 @@ public class ValueTests { @Test public void colorUpdate() { ColorValue v = new ColorValue(ColorMode.RGB, "fancyON", "fancyOFF", 77); - v.update((State) v.parseCommand(p(v, "255,255,255"))); + v.update(v.parseCommand(p(v, "255,255,255"))); - HSBType hsb = (HSBType) v.parseCommand(p(v, "OFF")); + HSBType hsb = v.parseCommand(p(v, "OFF")); assertThat(hsb.getBrightness().intValue(), is(0)); v.update(hsb); - hsb = (HSBType) v.parseCommand(p(v, "ON")); + hsb = v.parseCommand(p(v, "ON")); assertThat(hsb.getBrightness().intValue(), is(77)); - hsb = (HSBType) v.parseCommand(p(v, "0")); + hsb = v.parseCommand(p(v, "0")); assertThat(hsb.getBrightness().intValue(), is(0)); - hsb = (HSBType) v.parseCommand(p(v, "1")); + hsb = v.parseCommand(p(v, "1")); assertThat(hsb.getBrightness().intValue(), is(1)); assertThat(v.parseMessage(new StringType("")), is(UnDefType.NULL)); @@ -218,8 +217,13 @@ public class ValueTests { assertThat(command, is(new QuantityType<>(20, Units.PERCENT))); assertThat(v.getMQTTpublishValue(command, null), is("20")); - // Test with command without units - command = v.parseCommand(new QuantityType<>("20")); + // Test with command with units.ONE + command = v.parseCommand(new QuantityType<>("0.2")); + assertThat(command, is(new QuantityType<>(20, Units.PERCENT))); + assertThat(v.getMQTTpublishValue(command, null), is("20")); + + // Test with command with DecimalType + command = v.parseCommand(new DecimalType(20)); assertThat(command, is(new QuantityType<>(20, Units.PERCENT))); assertThat(v.getMQTTpublishValue(command, null), is("20")); } @@ -241,7 +245,7 @@ public class ValueTests { // Test with exact percent Command command = new PercentType(27); - assertThat(v.parseCommand((Command) command), is(command)); + assertThat(v.parseCommand(command), is(command)); assertThat(v.getMQTTpublishValue(command, null), is("27")); // Test formatting 0/100 @@ -272,7 +276,7 @@ public class ValueTests { // Test with exact percent Command command = new PercentType(27); - assertThat(v.parseCommand((Command) command), is(command)); + assertThat(v.parseCommand(command), is(command)); assertThat(v.getMQTTpublishValue(command, null), is("27")); // Test formatting 0/100 @@ -338,7 +342,7 @@ public class ValueTests { 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)); + PercentType command = v.parseCommand(new DecimalType(0.2)); assertEquals(command.floatValue(), 11.11f, 0.01f); } @@ -348,26 +352,26 @@ public class ValueTests { null, null); // Normal operation. - PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0")); + PercentType command = v.parseCommand(new DecimalType("6.0")); assertEquals(command.floatValue(), 50.0f, 0.01f); v.update(command); - command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE); + command = v.parseCommand(IncreaseDecreaseType.INCREASE); assertEquals(command.floatValue(), 55.0f, 0.01f); - command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE); + command = v.parseCommand(IncreaseDecreaseType.DECREASE); assertEquals(command.floatValue(), 45.0f, 0.01f); // Lower limit. - command = (PercentType) v.parseCommand(new DecimalType("1.1")); + command = v.parseCommand(new DecimalType("1.1")); assertEquals(command.floatValue(), 1.0f, 0.01f); v.update(command); - command = (PercentType) v.parseCommand(IncreaseDecreaseType.DECREASE); + command = v.parseCommand(IncreaseDecreaseType.DECREASE); assertEquals(command.floatValue(), 0.0f, 0.01f); // Upper limit. - command = (PercentType) v.parseCommand(new DecimalType("10.8")); + command = v.parseCommand(new DecimalType("10.8")); assertEquals(command.floatValue(), 98.0f, 0.01f); v.update(command); - command = (PercentType) v.parseCommand(IncreaseDecreaseType.INCREASE); + command = v.parseCommand(IncreaseDecreaseType.INCREASE); assertEquals(command.floatValue(), 100.0f, 0.01f); } @@ -377,26 +381,26 @@ public class ValueTests { null, null); // Normal operation. - PercentType command = (PercentType) v.parseCommand(new DecimalType("6.0")); + PercentType command = v.parseCommand(new DecimalType("6.0")); assertEquals(command.floatValue(), 50.0f, 0.01f); v.update(command); - command = (PercentType) v.parseCommand(UpDownType.UP); + command = v.parseCommand(UpDownType.UP); assertEquals(command.floatValue(), 55.0f, 0.01f); - command = (PercentType) v.parseCommand(UpDownType.DOWN); + command = v.parseCommand(UpDownType.DOWN); assertEquals(command.floatValue(), 45.0f, 0.01f); // Lower limit. - command = (PercentType) v.parseCommand(new DecimalType("1.1")); + command = v.parseCommand(new DecimalType("1.1")); assertEquals(command.floatValue(), 1.0f, 0.01f); v.update(command); - command = (PercentType) v.parseCommand(UpDownType.DOWN); + command = v.parseCommand(UpDownType.DOWN); assertEquals(command.floatValue(), 0.0f, 0.01f); // Upper limit. - command = (PercentType) v.parseCommand(new DecimalType("10.8")); + command = v.parseCommand(new DecimalType("10.8")); assertEquals(command.floatValue(), 98.0f, 0.01f); v.update(command); - command = (PercentType) v.parseCommand(UpDownType.UP); + command = v.parseCommand(UpDownType.UP); assertEquals(command.floatValue(), 100.0f, 0.01f); } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java index f51ebc33996..78549ef16a7 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/component/SensorTests.java @@ -77,7 +77,7 @@ public class SensorTests extends AbstractComponentTests { publishMessage("zigbee2mqtt/sensor/state", "20"); assertState(component, Sensor.SENSOR_CHANNEL_ID, new QuantityType<>(20, Units.WATT)); assertThat(component.getChannel(Sensor.SENSOR_CHANNEL_ID).getState().getCache().createStateDescription(true) - .build().getPattern(), is("%s W")); + .build().getPattern(), is("%.0f %unit%")); waitForAssert(() -> assertState(component, Sensor.SENSOR_CHANNEL_ID, UnDefType.UNDEF), 5000, 200);