[miele] Temperature channel improvements: UoM, categories and descriptions (#11329)

* Improvements for temperature channels

Fixes #11317

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Added jlaur as miele binding maintainer

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fix spinning speed for washing machines

Fixes #11317

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Added time as category for DateTime-related channels

Fixes #11317

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Elapsed/remaining time channels are no longer marked as advanced.

Fixes #11317

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fixed type for temperature item examples.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Document all states (cross-appliance).

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Improved error handling for getTemperatureState

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Split current/target temperature into two channel types for label reuse

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Fix possible NullPointerException

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Distinguish between oven program temperatures

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Mark oven program temperature 1 and 2 as advanced.

Fixes #11317

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
jlaur 2021-10-02 19:57:22 +02:00 committed by GitHub
parent b1f412377f
commit 8d38276dce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 205 additions and 112 deletions

View File

@ -168,7 +168,7 @@
/bundles/org.openhab.binding.meteoalerte/ @clinique /bundles/org.openhab.binding.meteoalerte/ @clinique
/bundles/org.openhab.binding.meteoblue/ @9037568 /bundles/org.openhab.binding.meteoblue/ @9037568
/bundles/org.openhab.binding.meteostick/ @cdjackson /bundles/org.openhab.binding.meteostick/ @cdjackson
/bundles/org.openhab.binding.miele/ @kgoderis /bundles/org.openhab.binding.miele/ @kgoderis @jlaur
/bundles/org.openhab.binding.mielecloud/ @BjoernLange /bundles/org.openhab.binding.mielecloud/ @BjoernLange
/bundles/org.openhab.binding.mihome/ @pboos /bundles/org.openhab.binding.mihome/ @pboos
/bundles/org.openhab.binding.miio/ @marcelrv /bundles/org.openhab.binding.miio/ @marcelrv

View File

@ -64,8 +64,8 @@ demo.items:
``` ```
String MieleFridgeState (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:state"} String MieleFridgeState (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:state"}
Switch MieleFridgeSuperCool (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:supercool"} Switch MieleFridgeSuperCool (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:supercool"}
Number MieleFridgeCurrent (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:current"} Number:Temperature MieleFridgeCurrent (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:current"}
Number MieleFridgeTarget (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:target"} Number:Temperature MieleFridgeTarget (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:target"}
Contact MieleFridgeDoor (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:door"} Contact MieleFridgeDoor (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:door"}
Switch MieleFridgeStart (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:start"} Switch MieleFridgeStart (gMiele,gMieleFridge) {channel="miele:fridge:dilbeek:fridge:start"}
``` ```

View File

@ -14,6 +14,11 @@ package org.openhab.binding.miele.internal;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
/** /**
* The {@link ExtendedDeviceStateUtil} class contains utility methods for parsing * The {@link ExtendedDeviceStateUtil} class contains utility methods for parsing
* ExtendedDeviceState information * ExtendedDeviceState information
@ -22,6 +27,7 @@ import java.nio.charset.StandardCharsets;
*/ */
public class ExtendedDeviceStateUtil { public class ExtendedDeviceStateUtil {
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII); private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
private static final String TEMPERATURE_UNDEFINED = "32768";
/** /**
* Convert byte array to hex representation. * Convert byte array to hex representation.
@ -46,4 +52,15 @@ public class ExtendedDeviceStateUtil {
public static byte[] stringToBytes(String input) { public static byte[] stringToBytes(String input) {
return input.getBytes(StandardCharsets.ISO_8859_1); return input.getBytes(StandardCharsets.ISO_8859_1);
} }
/**
* Convert string to Number:Temperature state with unit Celcius
*/
public static State getTemperatureState(String s) throws NumberFormatException {
if (TEMPERATURE_UNDEFINED.equals(s)) {
return UnDefType.UNDEF;
}
int temperature = Integer.parseInt(s);
return new QuantityType<>(temperature, SIUnits.CELSIUS);
}
} }

View File

@ -58,8 +58,24 @@ public class MieleBindingConstants {
public static final String MIELE_DEVICE_CLASS_FRIDGE_FREEZER = "FridgeFreezer"; public static final String MIELE_DEVICE_CLASS_FRIDGE_FREEZER = "FridgeFreezer";
// Miele appliance states // Miele appliance states
public static final int STATE_UNKNOWN = 0;
public static final int STATE_OFF = 1;
public static final int STATE_STAND_BY = 2;
public static final int STATE_PROGRAMMED = 3;
public static final int STATE_WAITING_TO_START = 4;
public static final int STATE_RUNNING = 5;
public static final int STATE_PAUSED = 6;
public static final int STATE_END = 7;
public static final int STATE_FAILURE = 8;
public static final int STATE_ABORT = 9;
public static final int STATE_IDLE = 10;
public static final int STATE_RINSE_HOLD = 11;
public static final int STATE_SERVICE = 12;
public static final int STATE_SUPER_FREEZING = 13; public static final int STATE_SUPER_FREEZING = 13;
public static final int STATE_SUPER_COOLING = 14; public static final int STATE_SUPER_COOLING = 14;
public static final int STATE_SUPER_HEATING = 15;
public static final int STATE_LOCKED = 145;
public static final int STATE_NOT_CONNECTED = 255;
// Bridge config properties // Bridge config properties
public static final String HOST = "ipAddress"; public static final String HOST = "ipAddress";

View File

@ -17,10 +17,11 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.SUPERCOOL
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State; import org.openhab.core.types.State;
import org.openhab.core.types.Type; import org.openhab.core.types.Type;
@ -43,16 +44,16 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
COMPANY_ID("companyId", "companyId", StringType.class, true), COMPANY_ID("companyId", "companyId", StringType.class, true),
STATE("state", "state", StringType.class, false), STATE("state", "state", StringType.class, false),
SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false), SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
FRIDGECURRENTTEMP("currentTemperature", "current", DecimalType.class, false) { FRIDGECURRENTTEMP("currentTemperature", "current", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
FRIDGETARGETTEMP("targetTemperature", "target", DecimalType.class, false) { FRIDGETARGETTEMP("targetTemperature", "target", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
DOOR("signalDoor", "door", OpenClosedType.class, false) { DOOR("signalDoor", "door", OpenClosedType.class, false) {
@ -142,6 +143,15 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
return null; return null;
} }
public State getTemperatureState(String s) {
try {
return ExtendedDeviceStateUtil.getTemperatureState(s);
} catch (NumberFormatException e) {
logger.warn("An exception occurred while converting '{}' into a State", s);
return UnDefType.UNDEF;
}
}
public String getMieleEnum(String s, DeviceMetaData dmd) { public String getMieleEnum(String s, DeviceMetaData dmd) {
if (dmd.MieleEnum != null) { if (dmd.MieleEnum != null) {
for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) { for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) {

View File

@ -18,10 +18,11 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.SUPERFREE
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State; import org.openhab.core.types.State;
import org.openhab.core.types.Type; import org.openhab.core.types.Type;
@ -48,28 +49,28 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
FRIDGESTATE("fridgeState", "fridgestate", StringType.class, false), FRIDGESTATE("fridgeState", "fridgestate", StringType.class, false),
SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false), SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
SUPERFREEZE(null, SUPERFREEZE_CHANNEL_ID, OnOffType.class, false), SUPERFREEZE(null, SUPERFREEZE_CHANNEL_ID, OnOffType.class, false),
FREEZERCURRENTTEMP("freezerCurrentTemperature", "freezercurrent", DecimalType.class, false) { FREEZERCURRENTTEMP("freezerCurrentTemperature", "freezercurrent", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
FREEZERTARGETTEMP("freezerTargetTemperature", "freezertarget", DecimalType.class, false) { FREEZERTARGETTEMP("freezerTargetTemperature", "freezertarget", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
FRIDGECURRENTTEMP("fridgeCurrentTemperature", "fridgecurrent", DecimalType.class, false) { FRIDGECURRENTTEMP("fridgeCurrentTemperature", "fridgecurrent", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
FRIDGETARGETTEMP("fridgeTargetTemperature", "fridgetarget", DecimalType.class, false) { FRIDGETARGETTEMP("fridgeTargetTemperature", "fridgetarget", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
DOOR("signalDoor", "door", OpenClosedType.class, false) { DOOR("signalDoor", "door", OpenClosedType.class, false) {
@ -160,6 +161,15 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
return null; return null;
} }
public State getTemperatureState(String s) {
try {
return ExtendedDeviceStateUtil.getTemperatureState(s);
} catch (NumberFormatException e) {
logger.warn("An exception occurred while converting '{}' into a State", s);
return UnDefType.UNDEF;
}
}
public String getMieleEnum(String s, DeviceMetaData dmd) { public String getMieleEnum(String s, DeviceMetaData dmd) {
if (dmd.MieleEnum != null) { if (dmd.MieleEnum != null) {
for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) { for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) {

View File

@ -18,11 +18,12 @@ import java.util.Date;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TimeZone; import java.util.TimeZone;
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.types.State; import org.openhab.core.types.State;
import org.openhab.core.types.Type; import org.openhab.core.types.Type;
@ -104,28 +105,28 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
return getState(dateFormatter.format(date)); return getState(dateFormatter.format(date));
} }
}, },
TARGET_TEMP("targetTemperature", "target", DecimalType.class, false) { TARGET_TEMP("targetTemperature", "target", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
MEASURED_TEMP("measuredTemperature", "measured", DecimalType.class, false) { MEASURED_TEMP("measuredTemperature", "measured", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
DEVICE_TEMP_ONE("deviceTemperature1", "temp1", DecimalType.class, false) { DEVICE_TEMP_ONE("deviceTemperature1", "temp1", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
DEVICE_TEMP_TWO("deviceTemperature2", "temp2", DecimalType.class, false) { DEVICE_TEMP_TWO("deviceTemperature2", "temp2", QuantityType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
DOOR("signalDoor", "door", OpenClosedType.class, false) { DOOR("signalDoor", "door", OpenClosedType.class, false) {
@ -216,6 +217,15 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
return null; return null;
} }
public State getTemperatureState(String s) {
try {
return ExtendedDeviceStateUtil.getTemperatureState(s);
} catch (NumberFormatException e) {
logger.warn("An exception occurred while converting '{}' into a State", s);
return UnDefType.UNDEF;
}
}
public String getMieleEnum(String s, DeviceMetaData dmd) { public String getMieleEnum(String s, DeviceMetaData dmd) {
if (dmd.MieleEnum != null) { if (dmd.MieleEnum != null) {
for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) { for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) {

View File

@ -23,9 +23,9 @@ import java.util.Map.Entry;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
@ -111,10 +111,10 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
return getState(dateFormatter.format(date)); return getState(dateFormatter.format(date));
} }
}, },
TARGET_TEMP("targetTemperature", "target", DecimalType.class, false, false) { TARGET_TEMP("targetTemperature", "target", QuantityType.class, false, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
return getState(s); return getTemperatureState(s);
} }
}, },
SPINNING_SPEED("spinningSpeed", "spinningspeed", StringType.class, false, false) { SPINNING_SPEED("spinningSpeed", "spinningspeed", StringType.class, false, false) {
@ -126,7 +126,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
if ("256".equals(s)) { if ("256".equals(s)) {
return getState("Rinsing"); return getState("Rinsing");
} }
return getState(Integer.toString((Integer.valueOf(s) * 10))); return getState(Integer.toString((Integer.valueOf(s))));
} }
}, },
DOOR("signalDoor", "door", OpenClosedType.class, false, false) { DOOR("signalDoor", "door", OpenClosedType.class, false, false) {
@ -223,6 +223,15 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
return null; return null;
} }
public State getTemperatureState(String s) {
try {
return ExtendedDeviceStateUtil.getTemperatureState(s);
} catch (NumberFormatException e) {
logger.warn("An exception occurred while converting '{}' into a State", s);
return UnDefType.UNDEF;
}
}
public String getMieleEnum(String s, DeviceMetaData dmd) { public String getMieleEnum(String s, DeviceMetaData dmd) {
if (dmd.MieleEnum != null) { if (dmd.MieleEnum != null) {
for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) { for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) {

View File

@ -4,14 +4,14 @@
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<channel-type id="state" advanced="false"> <channel-type id="state">
<item-type>String</item-type> <item-type>String</item-type>
<label>Status</label> <label>Status</label>
<description>Current status of the appliance</description> <description>Current status of the appliance</description>
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="program" advanced="false"> <channel-type id="program">
<item-type>String</item-type> <item-type>String</item-type>
<label>Program</label> <label>Program</label>
<description>Current program or function running on the appliance</description> <description>Current program or function running on the appliance</description>
@ -25,7 +25,7 @@
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="phase" advanced="false"> <channel-type id="phase">
<item-type>String</item-type> <item-type>String</item-type>
<label>Phase</label> <label>Phase</label>
<description>Current phase of the program running on the appliance</description> <description>Current phase of the program running on the appliance</description>
@ -36,6 +36,7 @@
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>Start Time</label> <label>Start Time</label>
<description>Programmed start time of the program</description> <description>Programmed start time of the program</description>
<category>Time</category>
<state readOnly="true" pattern="%1$tH:%1$tM"></state> <state readOnly="true" pattern="%1$tH:%1$tM"></state>
</channel-type> </channel-type>
@ -43,37 +44,40 @@
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>Duration</label> <label>Duration</label>
<description>Duration of the program running on the appliance</description> <description>Duration of the program running on the appliance</description>
<category>Time</category>
<state readOnly="true" pattern="%1$tH:%1$tM"></state> <state readOnly="true" pattern="%1$tH:%1$tM"></state>
</channel-type> </channel-type>
<channel-type id="elapsed" advanced="true"> <channel-type id="elapsed">
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>Elapsed Time</label> <label>Elapsed Time</label>
<description>Time elapsed in the program running on the appliance</description> <description>Time elapsed in the program running on the appliance</description>
<category>Time</category>
<state readOnly="true" pattern="%1$tH:%1$tM"></state> <state readOnly="true" pattern="%1$tH:%1$tM"></state>
</channel-type> </channel-type>
<channel-type id="finish" advanced="true"> <channel-type id="finish">
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>Finish Time</label> <label>Finish Time</label>
<description>Time to finish the program running on the appliance</description> <description>Time to finish the program running on the appliance</description>
<category>Time</category>
<state readOnly="true" pattern="%1$tH:%1$tM"></state> <state readOnly="true" pattern="%1$tH:%1$tM"></state>
</channel-type> </channel-type>
<channel-type id="door" advanced="false"> <channel-type id="door">
<item-type>Contact</item-type> <item-type>Contact</item-type>
<label>Door</label> <label>Door</label>
<description>Current state of the door of the appliance</description> <description>Current state of the door of the appliance</description>
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="switch" advanced="false"> <channel-type id="switch">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Switch</label> <label>Switch</label>
<description>Switch the appliance on or off</description> <description>Switch the appliance on or off</description>
</channel-type> </channel-type>
<channel-type id="stop" advanced="false"> <channel-type id="stop">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Stop</label> <label>Stop</label>
<description>Stop the appliance</description> <description>Stop the appliance</description>
@ -86,98 +90,66 @@
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="target" advanced="true"> <channel-type id="temperature" advanced="true">
<item-type>Number</item-type> <item-type>Number:Temperature</item-type>
<label>Target Temperature</label>
<description>Target temperature to be reached by the oven</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="measured" advanced="true">
<item-type>Number</item-type>
<label>Measured Temperature</label>
<description>Actual measured temperature in the oven</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="temp" advanced="true">
<item-type>Number</item-type>
<label>Temperature</label> <label>Temperature</label>
<description>Program temperature in the oven</description> <description>Temperature reported by the appliance</description>
<state readOnly="true"></state> <category>Temperature</category>
<state readOnly="true" pattern="%.0f %unit%"/>
</channel-type> </channel-type>
<channel-type id="supercool" advanced="false"> <channel-type id="currentTemperature">
<item-type>Number:Temperature</item-type>
<label>Current Temperature</label>
<description>Current temperature of the appliance</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.0f %unit%"/>
</channel-type>
<channel-type id="targetTemperature">
<item-type>Number:Temperature</item-type>
<label>Target Temperature</label>
<description>Target temperature to be reached by the appliance</description>
<category>Temperature</category>
<state readOnly="true" pattern="%.0f %unit%"/>
</channel-type>
<channel-type id="supercool">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Super Cool</label> <label>Super Cool</label>
<description>Start Super Cooling</description> <description>Start Super Cooling</description>
<state readOnly="false"></state> <state readOnly="false"></state>
</channel-type> </channel-type>
<channel-type id="current" advanced="false"> <channel-type id="freezerstate">
<item-type>Number</item-type>
<label>Current Temperature</label>
<description>Current temperature in the fridge</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="freezerstate" advanced="false">
<item-type>String</item-type> <item-type>String</item-type>
<label>Status</label> <label>Status</label>
<description>Current status of the freezer compartment</description> <description>Current status of the freezer compartment</description>
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="fridgestate" advanced="false"> <channel-type id="fridgestate">
<item-type>String</item-type> <item-type>String</item-type>
<label>Status</label> <label>Status</label>
<description>Current status of the fridge compartment</description> <description>Current status of the fridge compartment</description>
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="superfreeze" advanced="false"> <channel-type id="superfreeze">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Super Freeze</label> <label>Super Freeze</label>
<description>Start Super Freezing</description> <description>Start Super Freezing</description>
<state readOnly="false"></state> <state readOnly="false"></state>
</channel-type> </channel-type>
<channel-type id="freezercurrent" advanced="false"> <channel-type id="plates">
<item-type>Number</item-type>
<label>Current Temperature</label>
<description>Current temperature in the freezer compartment</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="freezertarget" advanced="true">
<item-type>Number</item-type>
<label>Target Temperature</label>
<description>Target temperature to be reached by the freezer compartment</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="fridgecurrent" advanced="false">
<item-type>Number</item-type>
<label>Current Temperature</label>
<description>Current temperature in the fridge compartment</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="fridgetarget" advanced="true">
<item-type>Number</item-type>
<label>Target Temperature</label>
<description>Target temperature to be reached by the fridge compartment</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="plates" advanced="false">
<item-type>Number</item-type> <item-type>Number</item-type>
<label>Plates</label> <label>Plates</label>
<description>Number of heating zones/plates on the hob</description> <description>Number of heating zones/plates on the hob</description>
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="power" advanced="false"> <channel-type id="power">
<item-type>Number</item-type> <item-type>Number</item-type>
<label>Power Step</label> <label>Power Step</label>
<description>Power level of the heating zone/plate</description> <description>Power level of the heating zone/plate</description>
@ -191,14 +163,14 @@
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="time" advanced="true"> <channel-type id="time">
<item-type>String</item-type> <item-type>String</item-type>
<label>Remaining Time</label> <label>Remaining Time</label>
<description>Remaining time of the heating zone/plate</description> <description>Remaining time of the heating zone/plate</description>
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="ventilation" advanced="false"> <channel-type id="ventilation">
<item-type>Number</item-type> <item-type>Number</item-type>
<label>Ventilation Power</label> <label>Ventilation Power</label>
<description>Current ventilation power</description> <description>Current ventilation power</description>
@ -212,14 +184,14 @@
<state readOnly="true"></state> <state readOnly="true"></state>
</channel-type> </channel-type>
<channel-type id="powerConsumption" advanced="false"> <channel-type id="powerConsumption">
<item-type>Number:Power</item-type> <item-type>Number:Power</item-type>
<label>Power Consumption</label> <label>Power Consumption</label>
<description>Power consumption by the currently running program on the appliance</description> <description>Power consumption by the currently running program on the appliance</description>
<state readOnly="true" pattern="%.1f %unit%"/> <state readOnly="true" pattern="%.1f %unit%"/>
</channel-type> </channel-type>
<channel-type id="waterConsumption" advanced="false"> <channel-type id="waterConsumption">
<item-type>Number:Volume</item-type> <item-type>Number:Volume</item-type>
<label>Water Consumption</label> <label>Water Consumption</label>
<description>Water consumption by the currently running program on the appliance</description> <description>Water consumption by the currently running program on the appliance</description>

View File

@ -16,8 +16,12 @@
<channels> <channels>
<channel id="state" typeId="state"/> <channel id="state" typeId="state"/>
<channel id="supercool" typeId="supercool"/> <channel id="supercool" typeId="supercool"/>
<channel id="current" typeId="current"/> <channel id="current" typeId="currentTemperature">
<channel id="target" typeId="target"/> <description>Current temperature in the fridge</description>
</channel>
<channel id="target" typeId="targetTemperature">
<description>Target temperature to be reached by the fridge</description>
</channel>
<channel id="door" typeId="door"/> <channel id="door" typeId="door"/>
<channel id="start" typeId="switch"/> <channel id="start" typeId="switch"/>
</channels> </channels>

View File

@ -19,10 +19,18 @@
<channel id="fridgestate" typeId="fridgestate"/> <channel id="fridgestate" typeId="fridgestate"/>
<channel id="supercool" typeId="supercool"/> <channel id="supercool" typeId="supercool"/>
<channel id="superfreeze" typeId="superfreeze"/> <channel id="superfreeze" typeId="superfreeze"/>
<channel id="freezercurrent" typeId="freezercurrent"/> <channel id="freezercurrent" typeId="currentTemperature">
<channel id="freezertarget" typeId="freezertarget"/> <description>Current temperature in the freezer compartment</description>
<channel id="fridgecurrent" typeId="fridgecurrent"/> </channel>
<channel id="fridgetarget" typeId="fridgetarget"/> <channel id="freezertarget" typeId="targetTemperature">
<description>Target temperature to be reached by the freezer compartment</description>
</channel>
<channel id="fridgecurrent" typeId="currentTemperature">
<description>Current temperature in the fridge compartment</description>
</channel>
<channel id="fridgetarget" typeId="targetTemperature">
<description>Target temperature to be reached by the fridge compartment</description>
</channel>
<channel id="door" typeId="door"/> <channel id="door" typeId="door"/>
<channel id="start" typeId="switch"/> <channel id="start" typeId="switch"/>
</channels> </channels>

View File

@ -22,10 +22,21 @@
<channel id="duration" typeId="duration"/> <channel id="duration" typeId="duration"/>
<channel id="elapsed" typeId="elapsed"/> <channel id="elapsed" typeId="elapsed"/>
<channel id="finish" typeId="finish"/> <channel id="finish" typeId="finish"/>
<channel id="target" typeId="target"/> <channel id="target" typeId="targetTemperature">
<channel id="measured" typeId="measured"/> <description>Target temperature to be reached by the oven</description>
<channel id="temp1" typeId="temp"/> </channel>
<channel id="temp2" typeId="temp"/> <channel id="measured" typeId="currentTemperature">
<label>Measured Temperature</label>
<description>Actual measured temperature in the oven</description>
</channel>
<channel id="temp1" typeId="temperature">
<label>Program Temperature 1</label>
<description>Program temperature in the oven</description>
</channel>
<channel id="temp2" typeId="temperature">
<label>Program Temperature 2</label>
<description>Program temperature in the oven</description>
</channel>
<channel id="door" typeId="door"/> <channel id="door" typeId="door"/>
<channel id="stop" typeId="stop"/> <channel id="stop" typeId="stop"/>
<channel id="switch" typeId="switch"/> <channel id="switch" typeId="switch"/>

View File

@ -24,7 +24,10 @@
<channel id="finish" typeId="finish"/> <channel id="finish" typeId="finish"/>
<channel id="door" typeId="door"/> <channel id="door" typeId="door"/>
<channel id="switch" typeId="switch"/> <channel id="switch" typeId="switch"/>
<channel id="target" typeId="target"/> <channel id="target" typeId="targetTemperature">
<label>Temperature</label>
<description>Temperature of the selected program</description>
</channel>
<channel id="spinningspeed" typeId="spinningspeed"/> <channel id="spinningspeed" typeId="spinningspeed"/>
<channel id="powerConsumption" typeId="powerConsumption"/> <channel id="powerConsumption" typeId="powerConsumption"/>
<channel id="waterConsumption" typeId="waterConsumption"/> <channel id="waterConsumption" typeId="waterConsumption"/>

View File

@ -15,7 +15,10 @@ package org.openhab.binding.miele.internal;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.test.java.JavaTest; import org.openhab.core.test.java.JavaTest;
import org.openhab.core.types.UnDefType;
/** /**
* This class provides test cases for {@link * This class provides test cases for {@link
@ -45,4 +48,24 @@ public class ExtendedDeviceStateUtilTest extends JavaTest {
byte[] actual = ExtendedDeviceStateUtil.stringToBytes("\u0000\u0080\u0000"); byte[] actual = ExtendedDeviceStateUtil.stringToBytes("\u0000\u0080\u0000");
assertArrayEquals(expected, actual); assertArrayEquals(expected, actual);
} }
@Test
public void getTemperatureStateWellFormedValueReturnsQuantityType() throws NumberFormatException {
assertEquals(new QuantityType<>(42, SIUnits.CELSIUS), ExtendedDeviceStateUtil.getTemperatureState("42"));
}
@Test
public void getTemperatureStateMagicValueReturnsUndefined() throws NumberFormatException {
assertEquals(UnDefType.UNDEF, ExtendedDeviceStateUtil.getTemperatureState("32768"));
}
@Test
public void getTemperatureStateNonNumericValueThrowsNumberFormatException() {
assertThrows(NumberFormatException.class, () -> ExtendedDeviceStateUtil.getTemperatureState("A"));
}
@Test
public void getTemperatureStateNullValueThrowsNumberFormatException() {
assertThrows(NumberFormatException.class, () -> ExtendedDeviceStateUtil.getTemperatureState(null));
}
} }