[miele] Fix supercool/superfreeze for fridges/fridge-freezers (#11321)

* Fix typos.

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

* Do not expose getTypeClass through interface.

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

* Fix channel supercool for fridges and partially fix supercool/superfreeze for fridge-freezers.

Fixes #11320

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

* Fix two-way channel synchronization for supercool/superfreeze for fridge-freezer.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
jlaur 2021-09-30 09:00:26 +02:00 committed by GitHub
parent ff272bc828
commit b28413c6f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 80 additions and 71 deletions

View File

@ -39,7 +39,7 @@ public class ExtendedDeviceStateUtil {
/** /**
* Convert string consisting of 8 bit characters to byte array. * Convert string consisting of 8 bit characters to byte array.
* Note: This simple operation has been extracted and pure here to document * Note: This simple operation has been extracted and put here to document
* and ensure correct behavior for 8 bit characters that should be turned * and ensure correct behavior for 8 bit characters that should be turned
* into single bytes without any UTF-8 encoding. * into single bytes without any UTF-8 encoding.
*/ */

View File

@ -32,8 +32,11 @@ public class MieleBindingConstants {
public static final String PROTOCOL_PROPERTY_NAME = "protocol"; public static final String PROTOCOL_PROPERTY_NAME = "protocol";
public static final String SERIAL_NUMBER_PROPERTY_NAME = "serialNumber"; public static final String SERIAL_NUMBER_PROPERTY_NAME = "serialNumber";
public static final String EXTENDED_DEVICE_STATE_PROPERTY_NAME = "extendedDeviceState"; public static final String EXTENDED_DEVICE_STATE_PROPERTY_NAME = "extendedDeviceState";
public static final String STATE_PROPERTY_NAME = "state";
// Shared Channel ID's // Shared Channel ID's
public static final String SUPERCOOL_CHANNEL_ID = "supercool";
public static final String SUPERFREEZE_CHANNEL_ID = "superfreeze";
public static final String POWER_CONSUMPTION_CHANNEL_ID = "powerConsumption"; public static final String POWER_CONSUMPTION_CHANNEL_ID = "powerConsumption";
public static final String WATER_CONSUMPTION_CHANNEL_ID = "waterConsumption"; public static final String WATER_CONSUMPTION_CHANNEL_ID = "waterConsumption";
@ -51,6 +54,12 @@ public class MieleBindingConstants {
// Miele devices classes // Miele devices classes
public static final String MIELE_DEVICE_CLASS_COFFEE_SYSTEM = "CoffeeSystem"; public static final String MIELE_DEVICE_CLASS_COFFEE_SYSTEM = "CoffeeSystem";
public static final String MIELE_DEVICE_CLASS_FRIDGE = "Fridge";
public static final String MIELE_DEVICE_CLASS_FRIDGE_FREEZER = "FridgeFreezer";
// Miele appliance states
public static final int STATE_SUPER_FREEZING = 13;
public static final int STATE_SUPER_COOLING = 14;
// Bridge config properties // Bridge config properties
public static final String HOST = "ipAddress"; public static final String HOST = "ipAddress";

View File

@ -14,7 +14,6 @@ package org.openhab.binding.miele.internal.handler;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
import org.openhab.core.types.State; import org.openhab.core.types.State;
import org.openhab.core.types.Type;
/** /**
* The {@link ApplianceChannelSelector} class defines a common interface for * The {@link ApplianceChannelSelector} class defines a common interface for
@ -62,9 +61,4 @@ public interface ApplianceChannelSelector {
* @param dmd - the device meta data * @param dmd - the device meta data
*/ */
State getState(String s, DeviceMetaData dmd); State getState(String s, DeviceMetaData dmd);
/**
* Returns "compatible" Type for this datapoint
*/
Class<? extends Type> getTypeClass();
} }

View File

@ -52,14 +52,14 @@ public interface ApplianceStatusListener {
void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp); void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp);
/** /**
* This method us called whenever an appliance is removed. * This method is called whenever an appliance is removed.
* *
* @param appliance The XGW homedevice definition of the appliance that was removed * @param appliance The XGW homedevice definition of the appliance that was removed
*/ */
void onApplianceRemoved(HomeDevice appliance); void onApplianceRemoved(HomeDevice appliance);
/** /**
* This method us called whenever an appliance is added. * This method is called whenever an appliance is added.
* *
* @param appliance The XGW homedevice definition of the appliance that was removed * @param appliance The XGW homedevice definition of the appliance that was removed
*/ */

View File

@ -89,11 +89,6 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -160,11 +160,6 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -12,6 +12,8 @@
*/ */
package org.openhab.binding.miele.internal.handler; package org.openhab.binding.miele.internal.handler;
import static org.openhab.binding.miele.internal.MieleBindingConstants.SUPERCOOL_CHANNEL_ID;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -40,7 +42,7 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
BRAND_ID("brandId", "brandId", StringType.class, true), BRAND_ID("brandId", "brandId", StringType.class, true),
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", OnOffType.class, false), SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
FRIDGECURRENTTEMP("currentTemperature", "current", DecimalType.class, false) { FRIDGECURRENTTEMP("currentTemperature", "current", DecimalType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
@ -99,11 +101,6 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -12,6 +12,9 @@
*/ */
package org.openhab.binding.miele.internal.handler; package org.openhab.binding.miele.internal.handler;
import static org.openhab.binding.miele.internal.MieleBindingConstants.SUPERCOOL_CHANNEL_ID;
import static org.openhab.binding.miele.internal.MieleBindingConstants.SUPERFREEZE_CHANNEL_ID;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -43,8 +46,8 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
STATE("state", "state", StringType.class, false), STATE("state", "state", StringType.class, false),
FREEZERSTATE("freezerState", "freezerstate", StringType.class, false), FREEZERSTATE("freezerState", "freezerstate", StringType.class, false),
FRIDGESTATE("fridgeState", "fridgestate", StringType.class, false), FRIDGESTATE("fridgeState", "fridgestate", StringType.class, false),
SUPERCOOL(null, "supercool", OnOffType.class, false), SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
SUPERFREEZE(null, "superfreeze", OnOffType.class, false), SUPERFREEZE(null, SUPERFREEZE_CHANNEL_ID, OnOffType.class, false),
FREEZERCURRENTTEMP("freezerCurrentTemperature", "freezercurrent", DecimalType.class, false) { FREEZERCURRENTTEMP("freezerCurrentTemperature", "freezercurrent", DecimalType.class, false) {
@Override @Override
public State getState(String s, DeviceMetaData dmd) { public State getState(String s, DeviceMetaData dmd) {
@ -116,11 +119,6 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -12,10 +12,10 @@
*/ */
package org.openhab.binding.miele.internal.handler; package org.openhab.binding.miele.internal.handler;
import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID; import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier; import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
@ -39,7 +39,7 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
private final Logger logger = LoggerFactory.getLogger(FridgeFreezerHandler.class); private final Logger logger = LoggerFactory.getLogger(FridgeFreezerHandler.class);
public FridgeFreezerHandler(Thing thing) { public FridgeFreezerHandler(Thing thing) {
super(thing, FridgeFreezerChannelSelector.class, "FridgeFreezer"); super(thing, FridgeFreezerChannelSelector.class, MIELE_DEVICE_CLASS_FRIDGE_FREEZER);
} }
@Override @Override
@ -89,4 +89,34 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
channelID, command.toString()); channelID, command.toString());
} }
} }
@Override
protected void onAppliancePropertyChanged(DeviceProperty dp) {
super.onAppliancePropertyChanged(dp);
if (!dp.Name.equals(STATE_PROPERTY_NAME)) {
return;
}
// Supercool/superfreeze is not exposed directly as property, but can be deduced from state.
OnOffType superCoolState, superFreezeState;
if (dp.Value.equals(String.valueOf(STATE_SUPER_COOLING))) {
superCoolState = OnOffType.ON;
superFreezeState = OnOffType.OFF;
} else if (dp.Value.equals(String.valueOf(STATE_SUPER_FREEZING))) {
superCoolState = OnOffType.OFF;
superFreezeState = OnOffType.ON;
} else {
superCoolState = OnOffType.OFF;
superFreezeState = OnOffType.OFF;
}
ChannelUID superCoolChannelUid = new ChannelUID(getThing().getUID(), SUPERCOOL_CHANNEL_ID);
logger.trace("Update state of {} to {} through '{}'", superCoolChannelUid, superCoolState, dp.Name);
updateState(superCoolChannelUid, superCoolState);
ChannelUID superFreezeChannelUid = new ChannelUID(getThing().getUID(), SUPERFREEZE_CHANNEL_ID);
logger.trace("Update state of {} to {} through '{}'", superFreezeChannelUid, superFreezeState, dp.Name);
updateState(superFreezeChannelUid, superFreezeState);
}
} }

View File

@ -12,15 +12,16 @@
*/ */
package org.openhab.binding.miele.internal.handler; package org.openhab.binding.miele.internal.handler;
import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID; import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier; import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -39,7 +40,7 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
private final Logger logger = LoggerFactory.getLogger(FridgeHandler.class); private final Logger logger = LoggerFactory.getLogger(FridgeHandler.class);
public FridgeHandler(Thing thing) { public FridgeHandler(Thing thing) {
super(thing, FridgeChannelSelector.class, "Fridge"); super(thing, FridgeChannelSelector.class, MIELE_DEVICE_CLASS_FRIDGE);
} }
@Override @Override
@ -89,4 +90,19 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
channelID, command.toString()); channelID, command.toString());
} }
} }
@Override
protected void onAppliancePropertyChanged(DeviceProperty dp) {
super.onAppliancePropertyChanged(dp);
if (!dp.Name.equals(STATE_PROPERTY_NAME)) {
return;
}
// Supercool is not exposed directly as property, but can be deduced from state.
ChannelUID channelUid = new ChannelUID(getThing().getUID(), SUPERCOOL_CHANNEL_ID);
State state = dp.Value.equals(String.valueOf(STATE_SUPER_COOLING)) ? OnOffType.ON : OnOffType.OFF;
logger.trace("Update state of {} to {} through '{}'", channelUid, state, dp.Name);
updateState(channelUid, state);
}
} }

View File

@ -119,11 +119,6 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -86,11 +86,6 @@ public enum HoodChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -192,7 +192,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
this.onAppliancePropertyChanged(dp); this.onAppliancePropertyChanged(dp);
} }
private void onAppliancePropertyChanged(DeviceProperty dp) { protected void onAppliancePropertyChanged(DeviceProperty dp) {
try { try {
DeviceMetaData dmd = null; DeviceMetaData dmd = null;
if (dp.Metadata == null) { if (dp.Metadata == null) {

View File

@ -281,7 +281,7 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
listener.onApplianceStateChanged(applianceIdentifier, dco); listener.onApplianceStateChanged(applianceIdentifier, dco);
} }
} catch (Exception e) { } catch (Exception e) {
logger.debug("An exception occurred while quering an appliance : '{}'", logger.debug("An exception occurred while querying an appliance : '{}'",
e.getMessage()); e.getMessage());
} }
} }
@ -387,7 +387,7 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
break; break;
} }
case "value": { case "value": {
dp.Value = subparts[1]; dp.Value = StringUtils.trim(StringUtils.strip(subparts[1]));
break; break;
} }
case "id": { case "id": {
@ -600,7 +600,7 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
/** /**
* This method is called whenever the connection to the given {@link MieleBridge} is resumed. * This method is called whenever the connection to the given {@link MieleBridge} is resumed.
* *
* @param bridge the hue bridge the connection is resumed to * @param bridge the Miele bridge the connection is resumed to
*/ */
public void onConnectionResumed() { public void onConnectionResumed() {
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);

View File

@ -175,11 +175,6 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -157,11 +157,6 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -182,11 +182,6 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
return channelID; return channelID;
} }
@Override
public Class<? extends Type> getTypeClass() {
return typeClass;
}
@Override @Override
public boolean isProperty() { public boolean isProperty() {
return isProperty; return isProperty;

View File

@ -108,10 +108,10 @@
</channel-type> </channel-type>
<channel-type id="supercool" advanced="false"> <channel-type id="supercool" advanced="false">
<item-type>String</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="true"></state> <state readOnly="false"></state>
</channel-type> </channel-type>
<channel-type id="current" advanced="false"> <channel-type id="current" advanced="false">
@ -136,10 +136,10 @@
</channel-type> </channel-type>
<channel-type id="superfreeze" advanced="false"> <channel-type id="superfreeze" advanced="false">
<item-type>String</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="true"></state> <state readOnly="false"></state>
</channel-type> </channel-type>
<channel-type id="freezercurrent" advanced="false"> <channel-type id="freezercurrent" advanced="false">