[MQTT] Fix state description (#16866)

* fix state description

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Mark Herwege 2024-06-14 19:07:58 +02:00 committed by Ciprian Pascu
parent ff7ebd7ac4
commit b079e09b35
5 changed files with 49 additions and 37 deletions

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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 %%");
}
}

View File

@ -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);
}

View File

@ -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);