[miele] Clean up properties and improve reliability and performance (#11423)
* Use appliance cache for getting full UID with protocol prefix instead of relying on property. * Set bare protocol name as property. * Fix potential null pointer access warnings. * Remove unused import. * Renamed property protocol to protocolAdapter for correctness. * Add connectionType property. * Add appliance model property. * Remove useless properties brandId and companyId always having value MI. * Rename property dc to deviceClass and set it consistently (not only from auto-discovered things). * Added constants for remaining handlers with hardcoded device classes. * Fix SCA: AuthorContributionDescriptionCheck * Fix SCA: ModifierOrderCheck * Rename ExtendedDeviceStateUtil to be a bit more generic. * Extract device class string parsing to utility method. * Fix SCA: ForbiddenPackageUsageCheck * Fix redundant null check. * Fix potential null pointer access warnings. * Fix unsafe null type conversion (type annotations) * Share same configuration (UID) for all appliance types. * Refer to gateway instead of ZigBee network in configuration. * Remove dependency to seriaNumber property for multicast channel updates. * Simplified filtering of irrelevant device class. * Remove devices from remoteUid cache also when disappearing from gateway, although this is a quite rare scenario. * Add default i18n properties file. * Add partial Danish translation. Fixes #11422 Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
parent
dd4019c172
commit
745bf76569
|
@ -20,12 +20,12 @@ import org.openhab.core.types.State;
|
|||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link ExtendedDeviceStateUtil} class contains utility methods for parsing
|
||||
* ExtendedDeviceState information
|
||||
* The {@link DeviceUtil} class contains utility methods for extracting
|
||||
* and parsing device information, for example from ExtendedDeviceState.
|
||||
*
|
||||
* @author Jacob Laursen - Added power/water consumption channels
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
public class ExtendedDeviceStateUtil {
|
||||
public class DeviceUtil {
|
||||
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||
private static final String TEMPERATURE_UNDEFINED = "32768";
|
||||
|
|
@ -16,7 +16,7 @@ package org.openhab.binding.miele.internal;
|
|||
* The {@link FullyQualifiedApplianceIdentifier} class represents a fully qualified appliance identifier.
|
||||
* Example: "hdm:ZigBee:0123456789abcdef#210"
|
||||
*
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
public class FullyQualifiedApplianceIdentifier {
|
||||
private String uid;
|
||||
|
|
|
@ -28,8 +28,10 @@ public class MieleBindingConstants {
|
|||
|
||||
public static final String BINDING_ID = "miele";
|
||||
public static final String APPLIANCE_ID = "uid";
|
||||
public static final String DEVICE_CLASS = "dc";
|
||||
public static final String PROTOCOL_PROPERTY_NAME = "protocol";
|
||||
public static final String DEVICE_CLASS = "deviceClass";
|
||||
public static final String MODEL_PROPERTY_NAME = "model";
|
||||
public static final String PROTOCOL_ADAPTER_PROPERTY_NAME = "protocolAdapter";
|
||||
public static final String CONNECTION_TYPE_PROPERTY_NAME = "connectionType";
|
||||
|
||||
// JSON-RPC property names
|
||||
public static final String SERIAL_NUMBER_PROPERTY_NAME = "serialNumber";
|
||||
|
@ -65,8 +67,14 @@ public class MieleBindingConstants {
|
|||
|
||||
// Miele devices classes
|
||||
public static final String MIELE_DEVICE_CLASS_COFFEE_SYSTEM = "CoffeeSystem";
|
||||
public static final String MIELE_DEVICE_CLASS_DISHWASHER = "Dishwasher";
|
||||
public static final String MIELE_DEVICE_CLASS_FRIDGE = "Fridge";
|
||||
public static final String MIELE_DEVICE_CLASS_FRIDGE_FREEZER = "FridgeFreezer";
|
||||
public static final String MIELE_DEVICE_CLASS_HOB = "Hob";
|
||||
public static final String MIELE_DEVICE_CLASS_HOOD = "Hood";
|
||||
public static final String MIELE_DEVICE_CLASS_OVEN = "Oven";
|
||||
public static final String MIELE_DEVICE_CLASS_TUMBLE_DRYER = "TumbleDryer";
|
||||
public static final String MIELE_DEVICE_CLASS_WASHING_MACHINE = "WashingMachine";
|
||||
|
||||
// Miele appliance states
|
||||
public static final int STATE_UNKNOWN = 0;
|
||||
|
|
|
@ -35,8 +35,6 @@ import org.openhab.core.thing.ThingUID;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* The {@link MieleApplianceDiscoveryService} tracks appliances that are
|
||||
* associated with the Miele@Home gateway
|
||||
|
@ -47,9 +45,6 @@ import com.google.gson.JsonElement;
|
|||
*/
|
||||
public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements ApplianceStatusListener {
|
||||
|
||||
private static final String MIELE_APPLIANCE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.MieleAppliance";
|
||||
private static final String MIELE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.Miele";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MieleApplianceDiscoveryService.class);
|
||||
|
||||
private static final int SEARCH_TIME = 60;
|
||||
|
@ -104,16 +99,17 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
|
|||
Map<String, Object> properties = new HashMap<>(2);
|
||||
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
|
||||
properties.put(PROTOCOL_PROPERTY_NAME, applianceIdentifier.getProtocol());
|
||||
properties.put(MODEL_PROPERTY_NAME, appliance.getApplianceModel());
|
||||
String deviceClass = appliance.getDeviceClass();
|
||||
if (deviceClass != null) {
|
||||
properties.put(DEVICE_CLASS, deviceClass);
|
||||
}
|
||||
properties.put(PROTOCOL_ADAPTER_PROPERTY_NAME, appliance.ProtocolAdapterName);
|
||||
properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId());
|
||||
properties.put(SERIAL_NUMBER_PROPERTY_NAME, appliance.getSerialNumber());
|
||||
|
||||
for (JsonElement dc : appliance.DeviceClasses) {
|
||||
String dcStr = dc.getAsString();
|
||||
if (dcStr.contains(MIELE_CLASS) && !dcStr.equals(MIELE_APPLIANCE_CLASS)) {
|
||||
properties.put(DEVICE_CLASS, dcStr.substring(MIELE_CLASS.length()));
|
||||
break;
|
||||
}
|
||||
String connectionType = appliance.getConnectionType();
|
||||
if (connectionType != null) {
|
||||
properties.put(CONNECTION_TYPE_PROPERTY_NAME, connectionType);
|
||||
}
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
|
@ -146,22 +142,9 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
|
|||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
private ThingUID getThingUID(HomeDevice appliance) {
|
||||
ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
|
||||
String modelId = null;
|
||||
|
||||
for (JsonElement dc : appliance.DeviceClasses) {
|
||||
String dcStr = dc.getAsString();
|
||||
if (dcStr.contains(MIELE_CLASS) && !dcStr.equals(MIELE_APPLIANCE_CLASS)) {
|
||||
modelId = dcStr.substring(MIELE_CLASS.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
String modelId = appliance.getDeviceClass();
|
||||
|
||||
if (modelId != null) {
|
||||
ThingTypeUID thingTypeUID = getThingTypeUidFromModelId(modelId);
|
||||
|
@ -183,7 +166,7 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
|
|||
* coffeemachine. At least until it is known if any models are actually reported
|
||||
* as CoffeeMachine, we need this special mapping.
|
||||
*/
|
||||
if (modelId.equals(MIELE_DEVICE_CLASS_COFFEE_SYSTEM)) {
|
||||
if (MIELE_DEVICE_CLASS_COFFEE_SYSTEM.equals(modelId)) {
|
||||
return THING_TYPE_COFFEEMACHINE;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.openhab.binding.miele.internal.MieleBindingConstants;
|
|||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
|
||||
import org.openhab.core.config.discovery.mdns.internal.MDNSDiscoveryService;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
|
|
@ -43,14 +43,6 @@ public interface ApplianceStatusListener {
|
|||
*/
|
||||
void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceProperty dp);
|
||||
|
||||
/**
|
||||
* This method is called whenever a "property" of the given appliance has changed.
|
||||
*
|
||||
* @param serialNumber The serial number of the appliance that has changed
|
||||
* @param dco the POJO containing the new state of the property
|
||||
*/
|
||||
void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp);
|
||||
|
||||
/**
|
||||
* This method is called whenever an appliance is removed.
|
||||
*
|
||||
|
|
|
@ -42,8 +42,6 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
|
@ -88,9 +86,9 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(CoffeeMachineChannelSelector.class);
|
||||
|
||||
private final static Map<String, String> programs = Collections.<String, String> emptyMap();
|
||||
private static final Map<String, String> programs = Collections.<String, String> emptyMap();
|
||||
|
||||
private final static Map<String, String> phases = Collections.<String, String> emptyMap();
|
||||
private static final Map<String, String> phases = Collections.<String, String> emptyMap();
|
||||
|
||||
private final String mieleID;
|
||||
private final String channelID;
|
||||
|
|
|
@ -14,9 +14,7 @@ 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.MIELE_DEVICE_CLASS_COFFEE_SYSTEM;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
@ -49,8 +47,6 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
CoffeeMachineChannelSelector selector = (CoffeeMachineChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -60,9 +56,9 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
|
|||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOn");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOn");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOff");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOff");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -75,7 +71,7 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -13,13 +13,12 @@
|
|||
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.MIELE_DEVICE_CLASS_DISHWASHER;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.POWER_CONSUMPTION_CHANNEL_ID;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.WATER_CONSUMPTION_CHANNEL_ID;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
@ -51,7 +50,7 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
|||
private final Logger logger = LoggerFactory.getLogger(DishWasherHandler.class);
|
||||
|
||||
public DishWasherHandler(Thing thing) {
|
||||
super(thing, DishwasherChannelSelector.class, "Dishwasher");
|
||||
super(thing, DishwasherChannelSelector.class, MIELE_DEVICE_CLASS_DISHWASHER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,8 +59,6 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
DishwasherChannelSelector selector = (DishwasherChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -71,9 +68,9 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
|||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -86,7 +83,7 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -48,8 +48,6 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true, false),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true, false),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true, false),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true, false),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
|
@ -152,12 +150,12 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(DishwasherChannelSelector.class);
|
||||
|
||||
private final static Map<String, String> programs = Map.ofEntries(entry("26", "Pots & Pans"),
|
||||
private static final Map<String, String> programs = Map.ofEntries(entry("26", "Pots & Pans"),
|
||||
entry("27", "Clean Machine"), entry("28", "Economy"), entry("30", "Normal"), entry("32", "Sensor Wash"),
|
||||
entry("34", "Energy Saver"), entry("35", "China & Crystal"), entry("36", "Extra Quiet"),
|
||||
entry("37", "SaniWash"), entry("38", "QuickPowerWash"), entry("42", "Tall items"));
|
||||
|
||||
private final static Map<String, String> phases = Map.ofEntries(entry("2", "Pre-Wash"), entry("3", "Main Wash"),
|
||||
private static final Map<String, String> phases = Map.ofEntries(entry("2", "Pre-Wash"), entry("3", "Main Wash"),
|
||||
entry("4", "Rinses"), entry("6", "Final rinse"), entry("7", "Drying"), entry("8", "Finished"));
|
||||
|
||||
private final String mieleID;
|
||||
|
|
|
@ -17,7 +17,7 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -42,8 +42,6 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
|
||||
|
@ -148,7 +146,7 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
public State getTemperatureState(String s) {
|
||||
try {
|
||||
return ExtendedDeviceStateUtil.getTemperatureState(s);
|
||||
return DeviceUtil.getTemperatureState(s);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("An exception occurred while converting '{}' into a State", s);
|
||||
return UnDefType.UNDEF;
|
||||
|
|
|
@ -17,7 +17,7 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -43,8 +43,6 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
FREEZERSTATE("freezerState", "freezerstate", StringType.class, false),
|
||||
|
@ -165,7 +163,7 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
public State getTemperatureState(String s) {
|
||||
try {
|
||||
return ExtendedDeviceStateUtil.getTemperatureState(s);
|
||||
return DeviceUtil.getTemperatureState(s);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("An exception occurred while converting '{}' into a State", s);
|
||||
return UnDefType.UNDEF;
|
||||
|
|
|
@ -14,7 +14,6 @@ package org.openhab.binding.miele.internal.handler;
|
|||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
||||
|
||||
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.thing.ChannelUID;
|
||||
|
@ -48,8 +47,6 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
FridgeFreezerChannelSelector selector = (FridgeFreezerChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -59,17 +56,17 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
|||
switch (selector) {
|
||||
case SUPERCOOL: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startSuperCooling");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperCooling");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopSuperCooling");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperCooling");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SUPERFREEZE: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startSuperFreezing");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperFreezing");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopSuperFreezing");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperFreezing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -80,7 +77,7 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -94,7 +91,7 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
|||
protected void onAppliancePropertyChanged(DeviceProperty dp) {
|
||||
super.onAppliancePropertyChanged(dp);
|
||||
|
||||
if (!dp.Name.equals(STATE_PROPERTY_NAME)) {
|
||||
if (!STATE_PROPERTY_NAME.equals(dp.Name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ package org.openhab.binding.miele.internal.handler;
|
|||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
||||
|
||||
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.thing.ChannelUID;
|
||||
|
@ -49,8 +48,6 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
FridgeChannelSelector selector = (FridgeChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -60,15 +57,15 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
|||
switch (selector) {
|
||||
case SUPERCOOL: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startSuperCooling");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperCooling");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopSuperCooling");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperCooling");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case START: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -81,7 +78,7 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -95,7 +92,7 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
|||
protected void onAppliancePropertyChanged(DeviceProperty dp) {
|
||||
super.onAppliancePropertyChanged(dp);
|
||||
|
||||
if (!dp.Name.equals(STATE_PROPERTY_NAME)) {
|
||||
if (!STATE_PROPERTY_NAME.equals(dp.Name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,6 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PLATES("plateNumbers", "plates", DecimalType.class, true),
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
package org.openhab.binding.miele.internal.handler;
|
||||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_HOB;
|
||||
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
|
@ -26,7 +28,7 @@ import org.openhab.core.types.Command;
|
|||
public class HobHandler extends MieleApplianceHandler<HobChannelSelector> {
|
||||
|
||||
public HobHandler(Thing thing) {
|
||||
super(thing, HobChannelSelector.class, "Hob");
|
||||
super(thing, HobChannelSelector.class, MIELE_DEVICE_CLASS_HOB);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -39,8 +39,6 @@ public enum HoodChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
VENTILATION("ventilationPower", "ventilation", DecimalType.class, false),
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
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.PROTOCOL_PROPERTY_NAME;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_HOOD;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
@ -39,7 +38,7 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
|||
private final Logger logger = LoggerFactory.getLogger(HoodHandler.class);
|
||||
|
||||
public HoodHandler(Thing thing) {
|
||||
super(thing, HoodChannelSelector.class, "Hood");
|
||||
super(thing, HoodChannelSelector.class, MIELE_DEVICE_CLASS_HOOD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,8 +47,6 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
HoodChannelSelector selector = (HoodChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -59,15 +56,15 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
|||
switch (selector) {
|
||||
case LIGHT: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startLighting");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startLighting");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopLighting");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopLighting");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STOP: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -78,7 +75,7 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -20,8 +20,8 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
|
||||
|
@ -84,8 +84,13 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
|
||||
public ApplianceChannelSelector getValueSelectorFromChannelID(String valueSelectorText)
|
||||
throws IllegalArgumentException {
|
||||
for (ApplianceChannelSelector c : selectorType.getEnumConstants()) {
|
||||
if (c.getChannelID() != null && c.getChannelID().equals(valueSelectorText)) {
|
||||
E[] enumConstants = selectorType.getEnumConstants();
|
||||
if (enumConstants == null) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Could not get enum constants for value selector: %s", valueSelectorText));
|
||||
}
|
||||
for (ApplianceChannelSelector c : enumConstants) {
|
||||
if (c != null && c.getChannelID() != null && c.getChannelID().equals(valueSelectorText)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -95,8 +100,13 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
|
||||
public ApplianceChannelSelector getValueSelectorFromMieleID(String valueSelectorText)
|
||||
throws IllegalArgumentException {
|
||||
for (ApplianceChannelSelector c : selectorType.getEnumConstants()) {
|
||||
if (c.getMieleID() != null && c.getMieleID().equals(valueSelectorText)) {
|
||||
E[] enumConstants = selectorType.getEnumConstants();
|
||||
if (enumConstants == null) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Could not get enum constants for value selector: %s", valueSelectorText));
|
||||
}
|
||||
for (ApplianceChannelSelector c : enumConstants) {
|
||||
if (c != null && c.getMieleID() != null && c.getMieleID().equals(valueSelectorText)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -110,16 +120,14 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
final String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId != null) {
|
||||
this.applianceId = applianceId;
|
||||
if (getMieleBridgeHandler() != null) {
|
||||
ThingStatusInfo statusInfo = getBridge().getStatusInfo();
|
||||
updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription());
|
||||
}
|
||||
this.onBridgeConnectionResumed();
|
||||
}
|
||||
}
|
||||
|
||||
public void onBridgeConnectionResumed() {
|
||||
if (getMieleBridgeHandler() != null) {
|
||||
ThingStatusInfo statusInfo = getBridge().getStatusInfo();
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null && getMieleBridgeHandler() != null) {
|
||||
ThingStatusInfo statusInfo = bridge.getStatusInfo();
|
||||
updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription());
|
||||
}
|
||||
}
|
||||
|
@ -149,43 +157,32 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
public void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applicationIdentifier,
|
||||
DeviceClassObject dco) {
|
||||
String myApplianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String modelID = StringUtils.right(dco.DeviceClass,
|
||||
dco.DeviceClass.length() - new String("com.miele.xgw3000.gateway.hdm.deviceclasses.Miele").length());
|
||||
|
||||
if (myApplianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
if (modelID.equals(this.modelID)) {
|
||||
for (JsonElement prop : dco.Properties.getAsJsonArray()) {
|
||||
try {
|
||||
DeviceProperty dp = gson.fromJson(prop, DeviceProperty.class);
|
||||
if (!dp.Name.equals(EXTENDED_DEVICE_STATE_PROPERTY_NAME)) {
|
||||
dp.Value = StringUtils.trim(dp.Value);
|
||||
dp.Value = StringUtils.strip(dp.Value);
|
||||
}
|
||||
|
||||
onAppliancePropertyChanged(applicationIdentifier, dp);
|
||||
} catch (Exception p) {
|
||||
// Ignore - this is due to an unrecognized and not yet reverse-engineered array property
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp) {
|
||||
String mySerialNumber = getThing().getProperties().get(SERIAL_NUMBER_PROPERTY_NAME);
|
||||
if (!mySerialNumber.equals(serialNumber)) {
|
||||
if (myApplianceId == null || !myApplianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onAppliancePropertyChanged(dp);
|
||||
for (JsonElement prop : dco.Properties.getAsJsonArray()) {
|
||||
try {
|
||||
DeviceProperty dp = gson.fromJson(prop, DeviceProperty.class);
|
||||
if (dp == null) {
|
||||
continue;
|
||||
}
|
||||
if (!EXTENDED_DEVICE_STATE_PROPERTY_NAME.equals(dp.Name)) {
|
||||
dp.Value = dp.Value.trim();
|
||||
dp.Value = dp.Value.strip();
|
||||
}
|
||||
onAppliancePropertyChanged(applicationIdentifier, dp);
|
||||
} catch (Exception p) {
|
||||
// Ignore - this is due to an unrecognized and not yet reverse-engineered array property
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applicationIdentifier, DeviceProperty dp) {
|
||||
String myApplianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
|
||||
if (!myApplianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
if (myApplianceId == null || !myApplianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -202,14 +199,16 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
dmd = gson.fromJson(jsonMetaData, DeviceMetaData.class);
|
||||
// only keep the enum, if any - that's all we care for events we receive via multicast
|
||||
// all other fields are nulled
|
||||
dmd.LocalizedID = null;
|
||||
dmd.LocalizedValue = null;
|
||||
dmd.Filter = null;
|
||||
dmd.description = null;
|
||||
if (dmd != null) {
|
||||
dmd.LocalizedID = null;
|
||||
dmd.LocalizedValue = null;
|
||||
dmd.Filter = null;
|
||||
dmd.description = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dp.Metadata != null) {
|
||||
String metadata = StringUtils.replace(dp.Metadata.toString(), "enum", "MieleEnum");
|
||||
String metadata = dp.Metadata.toString().replace("enum", "MieleEnum");
|
||||
JsonObject jsonMetaData = (JsonObject) JsonParser.parseString(metadata);
|
||||
dmd = gson.fromJson(jsonMetaData, DeviceMetaData.class);
|
||||
metaDataCache.put(new StringBuilder().append(dp.Name).toString().trim(), metadata);
|
||||
|
@ -217,9 +216,9 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
|
||||
if (dp.Name.equals(EXTENDED_DEVICE_STATE_PROPERTY_NAME)) {
|
||||
if (!dp.Value.isEmpty()) {
|
||||
byte[] extendedStateBytes = ExtendedDeviceStateUtil.stringToBytes(dp.Value);
|
||||
byte[] extendedStateBytes = DeviceUtil.stringToBytes(dp.Value);
|
||||
logger.trace("Extended device state for {}: {}", getThing().getUID(),
|
||||
ExtendedDeviceStateUtil.bytesToHex(extendedStateBytes));
|
||||
DeviceUtil.bytesToHex(extendedStateBytes));
|
||||
if (this instanceof ExtendedDeviceStateListener) {
|
||||
((ExtendedDeviceStateListener) this).onApplianceExtendedStateChanged(extendedStateBytes);
|
||||
}
|
||||
|
@ -234,7 +233,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
logger.trace("{} is not a valid channel for a {}", dp.Name, modelID);
|
||||
}
|
||||
|
||||
String dpValue = StringUtils.trim(StringUtils.strip(dp.Value));
|
||||
String dpValue = dp.Value.strip().trim();
|
||||
|
||||
if (selector != null) {
|
||||
if (!selector.isProperty()) {
|
||||
|
@ -248,10 +247,11 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
} else {
|
||||
updateState(theChannelUID, UnDefType.UNDEF);
|
||||
}
|
||||
} else if (dpValue != null) {
|
||||
} else {
|
||||
logger.debug("Updating the property '{}' of '{}' to '{}'", selector.getChannelID(),
|
||||
getThing().getUID(), selector.getState(dpValue, dmd).toString());
|
||||
Map<String, String> properties = editProperties();
|
||||
@NonNull
|
||||
Map<@NonNull String, @NonNull String> properties = editProperties();
|
||||
properties.put(selector.getChannelID(), selector.getState(dpValue, dmd).toString());
|
||||
updateProperties(properties);
|
||||
}
|
||||
|
@ -317,9 +317,19 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
|
||||
|
||||
if (applianceId.equals(applianceIdentifier.getApplianceId())) {
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(PROTOCOL_PROPERTY_NAME, applianceIdentifier.getProtocol());
|
||||
@NonNull
|
||||
Map<@NonNull String, @NonNull String> properties = editProperties();
|
||||
properties.put(MODEL_PROPERTY_NAME, appliance.getApplianceModel());
|
||||
String deviceClass = appliance.getDeviceClass();
|
||||
if (deviceClass != null) {
|
||||
properties.put(DEVICE_CLASS, deviceClass);
|
||||
}
|
||||
properties.put(PROTOCOL_ADAPTER_PROPERTY_NAME, appliance.ProtocolAdapterName);
|
||||
properties.put(SERIAL_NUMBER_PROPERTY_NAME, appliance.getSerialNumber());
|
||||
String connectionType = appliance.getConnectionType();
|
||||
if (connectionType != null) {
|
||||
properties.put(CONNECTION_TYPE_PROPERTY_NAME, connectionType);
|
||||
}
|
||||
updateProperties(properties);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
|
@ -343,6 +353,9 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
}
|
||||
|
||||
protected boolean isResultProcessable(JsonElement result) {
|
||||
return result != null && !result.isJsonNull();
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Provided result is null");
|
||||
}
|
||||
return !result.isJsonNull();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,13 @@ import java.net.UnknownHostException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -44,7 +47,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.common.NamedThreadFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
|
@ -76,7 +79,10 @@ import com.google.gson.JsonParser;
|
|||
**/
|
||||
public class MieleBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_XGW3000);
|
||||
@NonNull
|
||||
public static final Set<@NonNull ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_XGW3000);
|
||||
|
||||
private static final String MIELE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.Miele";
|
||||
|
||||
private static final Pattern IP_PATTERN = Pattern
|
||||
.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
|
||||
|
@ -97,7 +103,9 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
protected ExecutorService executor;
|
||||
protected Future<?> eventListenerJob;
|
||||
|
||||
protected List<HomeDevice> previousHomeDevices = new CopyOnWriteArrayList<>();
|
||||
@NonNull
|
||||
protected Map<String, HomeDevice> cachedHomeDevicesByApplianceId = new ConcurrentHashMap<String, HomeDevice>();
|
||||
protected Map<String, HomeDevice> cachedHomeDevicesByRemoteUid = new ConcurrentHashMap<String, HomeDevice>();
|
||||
|
||||
protected URL url;
|
||||
protected Map<String, String> headers;
|
||||
|
@ -105,6 +113,8 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
// Data structures to de-JSONify whatever Miele appliances are sending us
|
||||
public class HomeDevice {
|
||||
|
||||
private static final String MIELE_APPLIANCE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.MieleAppliance";
|
||||
|
||||
public String Name;
|
||||
public String Status;
|
||||
public String ParentUID;
|
||||
|
@ -125,9 +135,49 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
return new FullyQualifiedApplianceIdentifier(this.UID);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getSerialNumber() {
|
||||
return Properties.get("serial.number").getAsString();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getRemoteUid() {
|
||||
JsonElement remoteUid = Properties.get("remote.uid");
|
||||
if (remoteUid == null) {
|
||||
// remote.uid and serial.number seems to be the same. If remote.uid
|
||||
// is missing for some reason, it makes sense to provide fallback
|
||||
// to serial number.
|
||||
return getSerialNumber();
|
||||
}
|
||||
return remoteUid.getAsString();
|
||||
}
|
||||
|
||||
public String getConnectionType() {
|
||||
JsonElement connectionType = Properties.get("connection.type");
|
||||
if (connectionType == null) {
|
||||
return null;
|
||||
}
|
||||
return connectionType.getAsString();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getApplianceModel() {
|
||||
JsonElement model = Properties.get("miele.model");
|
||||
if (model == null) {
|
||||
return "";
|
||||
}
|
||||
return model.getAsString();
|
||||
}
|
||||
|
||||
public String getDeviceClass() {
|
||||
for (JsonElement dc : DeviceClasses) {
|
||||
String dcStr = dc.getAsString();
|
||||
if (dcStr.contains(MIELE_CLASS) && !dcStr.equals(MIELE_APPLIANCE_CLASS)) {
|
||||
return dcStr.substring(MIELE_CLASS.length());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceClassObject {
|
||||
|
@ -206,95 +256,101 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
private Runnable pollingRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (IP_PATTERN.matcher((String) getConfig().get(HOST)).matches()) {
|
||||
try {
|
||||
if (isReachable((String) getConfig().get(HOST))) {
|
||||
currentBridgeConnectionState = true;
|
||||
} else {
|
||||
currentBridgeConnectionState = false;
|
||||
lastBridgeConnectionState = false;
|
||||
onConnectionLost();
|
||||
if (!IP_PATTERN.matcher((String) getConfig().get(HOST)).matches()) {
|
||||
logger.debug("Invalid IP address for the Miele@Home gateway : '{}'", getConfig().get(HOST));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (isReachable((String) getConfig().get(HOST))) {
|
||||
currentBridgeConnectionState = true;
|
||||
} else {
|
||||
currentBridgeConnectionState = false;
|
||||
lastBridgeConnectionState = false;
|
||||
onConnectionLost();
|
||||
}
|
||||
|
||||
if (!lastBridgeConnectionState && currentBridgeConnectionState) {
|
||||
logger.debug("Connection to Miele Gateway {} established.", getConfig().get(HOST));
|
||||
lastBridgeConnectionState = true;
|
||||
onConnectionResumed();
|
||||
}
|
||||
|
||||
if (!currentBridgeConnectionState || getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<HomeDevice> homeDevices = getHomeDevices();
|
||||
for (HomeDevice hd : homeDevices) {
|
||||
String key = hd.getApplianceIdentifier().getApplianceId();
|
||||
if (!cachedHomeDevicesByApplianceId.containsKey(key)) {
|
||||
logger.debug("A new appliance with ID '{}' has been added", hd.UID);
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onApplianceAdded(hd);
|
||||
}
|
||||
}
|
||||
cachedHomeDevicesByApplianceId.put(key, hd);
|
||||
cachedHomeDevicesByRemoteUid.put(hd.getRemoteUid(), hd);
|
||||
}
|
||||
|
||||
if (!lastBridgeConnectionState && currentBridgeConnectionState) {
|
||||
logger.debug("Connection to Miele Gateway {} established.", getConfig().get(HOST));
|
||||
lastBridgeConnectionState = true;
|
||||
onConnectionResumed();
|
||||
@NonNull
|
||||
Set<@NonNull Entry<String, HomeDevice>> cachedEntries = cachedHomeDevicesByApplianceId.entrySet();
|
||||
@NonNull
|
||||
Iterator<@NonNull Entry<String, HomeDevice>> iterator = cachedEntries.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Entry<String, HomeDevice> cachedEntry = iterator.next();
|
||||
HomeDevice cachedHomeDevice = cachedEntry.getValue();
|
||||
if (!homeDevices.stream().anyMatch(d -> d.UID.equals(cachedHomeDevice.UID))) {
|
||||
logger.debug("The appliance with ID '{}' has been removed", cachedHomeDevice.UID);
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onApplianceRemoved(cachedHomeDevice);
|
||||
}
|
||||
cachedHomeDevicesByRemoteUid.remove(cachedHomeDevice.getRemoteUid());
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBridgeConnectionState) {
|
||||
if (getThing().getStatus() == ThingStatus.ONLINE) {
|
||||
List<HomeDevice> currentHomeDevices = getHomeDevices();
|
||||
for (HomeDevice hd : currentHomeDevices) {
|
||||
boolean isExisting = false;
|
||||
for (HomeDevice phd : previousHomeDevices) {
|
||||
if (phd.UID.equals(hd.UID)) {
|
||||
isExisting = true;
|
||||
break;
|
||||
for (Thing appliance : getThing().getThings()) {
|
||||
if (appliance.getStatus() == ThingStatus.ONLINE) {
|
||||
String applianceId = (String) appliance.getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = getApplianceIdentifierFromApplianceId(
|
||||
applianceId);
|
||||
|
||||
if (applianceIdentifier == null) {
|
||||
logger.error("The appliance with ID '{}' was not found in appliance list from bridge.",
|
||||
applianceId);
|
||||
continue;
|
||||
}
|
||||
|
||||
Object[] args = new Object[2];
|
||||
args[0] = applianceIdentifier.getUid();
|
||||
args[1] = true;
|
||||
JsonElement result = invokeRPC("HDAccess/getDeviceClassObjects", args);
|
||||
|
||||
if (result != null) {
|
||||
for (JsonElement obj : result.getAsJsonArray()) {
|
||||
try {
|
||||
DeviceClassObject dco = gson.fromJson(obj, DeviceClassObject.class);
|
||||
|
||||
// Skip com.prosyst.mbs.services.zigbee.hdm.deviceclasses.ReportingControl
|
||||
if (dco == null || !dco.DeviceClass.startsWith(MIELE_CLASS)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!isExisting) {
|
||||
logger.debug("A new appliance with ID '{}' has been added", hd.UID);
|
||||
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onApplianceAdded(hd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (HomeDevice hd : previousHomeDevices) {
|
||||
boolean isCurrent = false;
|
||||
for (HomeDevice chd : currentHomeDevices) {
|
||||
if (chd.UID.equals(hd.UID)) {
|
||||
isCurrent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isCurrent) {
|
||||
logger.debug("The appliance with ID '{}' has been removed", hd);
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onApplianceRemoved(hd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previousHomeDevices = currentHomeDevices;
|
||||
|
||||
for (Thing appliance : getThing().getThings()) {
|
||||
if (appliance.getStatus() == ThingStatus.ONLINE) {
|
||||
String applianceId = (String) appliance.getConfiguration().getProperties()
|
||||
.get(APPLIANCE_ID);
|
||||
String protocol = appliance.getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId,
|
||||
protocol);
|
||||
|
||||
Object[] args = new Object[2];
|
||||
args[0] = applianceIdentifier.getUid();
|
||||
args[1] = true;
|
||||
JsonElement result = invokeRPC("HDAccess/getDeviceClassObjects", args);
|
||||
|
||||
if (result != null) {
|
||||
for (JsonElement obj : result.getAsJsonArray()) {
|
||||
try {
|
||||
DeviceClassObject dco = gson.fromJson(obj, DeviceClassObject.class);
|
||||
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onApplianceStateChanged(applianceIdentifier, dco);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while querying an appliance : '{}'",
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
listener.onApplianceStateChanged(applianceIdentifier, dco);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while querying an appliance : '{}'",
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while polling an appliance :'{}'", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
logger.debug("Invalid IP address for the Miele@Home gateway : '{}'", getConfig().get(HOST));
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while polling an appliance :'{}'", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,6 +395,15 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
return devices;
|
||||
}
|
||||
|
||||
private FullyQualifiedApplianceIdentifier getApplianceIdentifierFromApplianceId(String applianceId) {
|
||||
HomeDevice homeDevice = this.cachedHomeDevicesByApplianceId.get(applianceId);
|
||||
if (homeDevice == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return homeDevice.getApplianceIdentifier();
|
||||
}
|
||||
|
||||
private Runnable eventListenerRunnable = () -> {
|
||||
if (IP_PATTERN.matcher((String) getConfig().get(INTERFACE)).matches()) {
|
||||
while (true) {
|
||||
|
@ -378,16 +443,16 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
DeviceProperty dp = new DeviceProperty();
|
||||
String id = null;
|
||||
|
||||
String[] parts = StringUtils.split(event, "&");
|
||||
String[] parts = event.split("&");
|
||||
for (String p : parts) {
|
||||
String[] subparts = StringUtils.split(p, "=");
|
||||
String[] subparts = p.split("=");
|
||||
switch (subparts[0]) {
|
||||
case "property": {
|
||||
dp.Name = subparts[1];
|
||||
break;
|
||||
}
|
||||
case "value": {
|
||||
dp.Value = StringUtils.trim(StringUtils.strip(subparts[1]));
|
||||
dp.Value = subparts[1].strip().trim();
|
||||
break;
|
||||
}
|
||||
case "id": {
|
||||
|
@ -403,15 +468,19 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
|
||||
// In XGW 3000 firmware 2.03 this was changed from UID (hdm:ZigBee:0123456789abcdef#210)
|
||||
// to serial number (001234567890)
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier;
|
||||
if (id.startsWith("hdm:")) {
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onAppliancePropertyChanged(new FullyQualifiedApplianceIdentifier(id),
|
||||
dp);
|
||||
}
|
||||
applianceIdentifier = new FullyQualifiedApplianceIdentifier(id);
|
||||
} else {
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onAppliancePropertyChanged(id, dp);
|
||||
HomeDevice device = cachedHomeDevicesByRemoteUid.get(id);
|
||||
if (device == null) {
|
||||
logger.debug("Multicast event not handled as id {} is unknown.", id);
|
||||
continue;
|
||||
}
|
||||
applianceIdentifier = device.getApplianceIdentifier();
|
||||
}
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onAppliancePropertyChanged(applianceIdentifier, dp);
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
try {
|
||||
|
@ -445,19 +514,27 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
}
|
||||
};
|
||||
|
||||
public JsonElement invokeOperation(FullyQualifiedApplianceIdentifier applianceIdentifier, String modelID,
|
||||
String methodName) {
|
||||
if (getThing().getStatus() == ThingStatus.ONLINE) {
|
||||
Object[] args = new Object[4];
|
||||
args[0] = applianceIdentifier.getUid();
|
||||
args[1] = "com.miele.xgw3000.gateway.hdm.deviceclasses.Miele" + modelID;
|
||||
args[2] = methodName;
|
||||
args[3] = null;
|
||||
return invokeRPC("HDAccess/invokeDCOOperation", args);
|
||||
} else {
|
||||
public JsonElement invokeOperation(String applianceId, String modelID, String methodName) {
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("The Bridge is offline - operations can not be invoked.");
|
||||
return null;
|
||||
}
|
||||
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = getApplianceIdentifierFromApplianceId(applianceId);
|
||||
if (applianceIdentifier == null) {
|
||||
logger.error(
|
||||
"The appliance with ID '{}' was not found in appliance list from bridge - operations can not be invoked.",
|
||||
applianceId);
|
||||
return null;
|
||||
}
|
||||
|
||||
Object[] args = new Object[4];
|
||||
args[0] = applianceIdentifier.getUid();
|
||||
args[1] = MIELE_CLASS + modelID;
|
||||
args[2] = methodName;
|
||||
args[3] = null;
|
||||
|
||||
return invokeRPC("HDAccess/invokeDCOOperation", args);
|
||||
}
|
||||
|
||||
protected JsonElement invokeRPC(String methodName, Object[] args) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
@ -49,8 +49,6 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
|
@ -167,7 +165,7 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(OvenChannelSelector.class);
|
||||
|
||||
private final static Map<String, String> phases = Map.ofEntries(entry("1", "Heating"), entry("2", "Temp. hold"),
|
||||
private static final Map<String, String> phases = Map.ofEntries(entry("1", "Heating"), entry("2", "Temp. hold"),
|
||||
entry("3", "Door Open"), entry("4", "Pyrolysis"), entry("7", "Lighting"), entry("8", "Searing phase"),
|
||||
entry("10", "Defrost"), entry("11", "Cooling down"), entry("12", "Energy save phase"));
|
||||
|
||||
|
@ -241,7 +239,7 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
public State getTemperatureState(String s) {
|
||||
try {
|
||||
return ExtendedDeviceStateUtil.getTemperatureState(s);
|
||||
return DeviceUtil.getTemperatureState(s);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("An exception occurred while converting '{}' into a State", s);
|
||||
return UnDefType.UNDEF;
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
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.PROTOCOL_PROPERTY_NAME;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_OVEN;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
@ -40,7 +39,7 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
|||
private final Logger logger = LoggerFactory.getLogger(OvenHandler.class);
|
||||
|
||||
public OvenHandler(Thing thing) {
|
||||
super(thing, OvenChannelSelector.class, "Oven");
|
||||
super(thing, OvenChannelSelector.class, MIELE_DEVICE_CLASS_OVEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,8 +48,6 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
OvenChannelSelector selector = (OvenChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -60,15 +57,15 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
|||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOn");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOn");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOff");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOff");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STOP: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -81,7 +78,7 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -47,8 +47,6 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
|
@ -155,7 +153,7 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(TumbleDryerChannelSelector.class);
|
||||
|
||||
private final static Map<String, String> programs = Map.ofEntries(entry("10", "Automatic Plus"),
|
||||
private static final Map<String, String> programs = Map.ofEntries(entry("10", "Automatic Plus"),
|
||||
entry("23", "Cottons hygiene"), entry("30", "Minimum iron"), entry("31", "Gentle minimum iron"),
|
||||
entry("40", "Woollens handcare"), entry("50", "Delicates"), entry("60", "Warm Air"),
|
||||
entry("70", "Cool air"), entry("80", "Express"), entry("90", "Cottons"), entry("100", "Gentle smoothing"),
|
||||
|
@ -165,7 +163,7 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
entry("240", "Smoothing"), entry("65000", "Cottons, auto load control"),
|
||||
entry("65001", "Minimum iron, auto load control"));
|
||||
|
||||
private final static Map<String, String> phases = Map.ofEntries(entry("1", "Programme running"),
|
||||
private static final Map<String, String> phases = Map.ofEntries(entry("1", "Programme running"),
|
||||
entry("2", "Drying"), entry("3", "Drying Machine iron"), entry("4", "Drying Hand iron"),
|
||||
entry("5", "Drying Normal"), entry("6", "Drying Normal+"), entry("7", "Cooling down"),
|
||||
entry("8", "Drying Hand iron"), entry("10", "Finished"));
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
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.PROTOCOL_PROPERTY_NAME;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_TUMBLE_DRYER;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
@ -40,7 +39,7 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
|||
private final Logger logger = LoggerFactory.getLogger(TumbleDryerHandler.class);
|
||||
|
||||
public TumbleDryerHandler(Thing thing) {
|
||||
super(thing, TumbleDryerChannelSelector.class, "TumbleDryer");
|
||||
super(thing, TumbleDryerChannelSelector.class, MIELE_DEVICE_CLASS_TUMBLE_DRYER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,8 +48,6 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
TumbleDryerChannelSelector selector = (TumbleDryerChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
@ -60,9 +57,9 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
|||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -75,7 +72,7 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -22,8 +22,7 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openhab.binding.miele.internal.ExtendedDeviceStateUtil;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
|
@ -50,8 +49,6 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true, false),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true, false),
|
||||
BRAND_ID("brandId", "brandId", StringType.class, true, false),
|
||||
COMPANY_ID("companyId", "companyId", StringType.class, true, false),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false, false),
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
|
@ -98,7 +95,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
try {
|
||||
date.setTime(Long.valueOf(StringUtils.trim(s)) * 60000);
|
||||
date.setTime(Long.valueOf(s.trim()) * 60000);
|
||||
} catch (Exception e) {
|
||||
date.setTime(0);
|
||||
}
|
||||
|
@ -174,7 +171,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(WashingMachineChannelSelector.class);
|
||||
|
||||
private final static Map<String, String> programs = Map.ofEntries(entry("1", "Cottons"), entry("3", "Minimum iron"),
|
||||
private static final Map<String, String> programs = Map.ofEntries(entry("1", "Cottons"), entry("3", "Minimum iron"),
|
||||
entry("4", "Delicates"), entry("8", "Woollens"), entry("9", "Silks"), entry("17", "Starch"),
|
||||
entry("18", "Rinse"), entry("21", "Drain/Spin"), entry("22", "Curtains"), entry("23", "Shirts"),
|
||||
entry("24", "Denim"), entry("27", "Proofing"), entry("29", "Sportswear"), entry("31", "Automatic Plus"),
|
||||
|
@ -183,7 +180,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
entry("95", "Down duvets"), entry("122", "Express 20"), entry("129", "Down filled items"),
|
||||
entry("133", "Cottons Eco"), entry("146", "QuickPowerWash"), entry("65532", "Mix"));
|
||||
|
||||
private final static Map<String, String> phases = Map.ofEntries(entry("1", "Pre-wash"), entry("4", "Washing"),
|
||||
private static final Map<String, String> phases = Map.ofEntries(entry("1", "Pre-wash"), entry("4", "Washing"),
|
||||
entry("5", "Rinses"), entry("7", "Clean"), entry("9", "Drain"), entry("10", "Spin"),
|
||||
entry("11", "Anti-crease"), entry("12", "Finished"));
|
||||
|
||||
|
@ -260,7 +257,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
public State getTemperatureState(String s) {
|
||||
try {
|
||||
return ExtendedDeviceStateUtil.getTemperatureState(s);
|
||||
return DeviceUtil.getTemperatureState(s);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("An exception occurred while converting '{}' into a State", s);
|
||||
return UnDefType.UNDEF;
|
||||
|
|
|
@ -13,13 +13,12 @@
|
|||
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.MIELE_DEVICE_CLASS_WASHING_MACHINE;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.POWER_CONSUMPTION_CHANNEL_ID;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.WATER_CONSUMPTION_CHANNEL_ID;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
@ -51,7 +50,7 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
|||
private final Logger logger = LoggerFactory.getLogger(WashingMachineHandler.class);
|
||||
|
||||
public WashingMachineHandler(Thing thing) {
|
||||
super(thing, WashingMachineChannelSelector.class, "WashingMachine");
|
||||
super(thing, WashingMachineChannelSelector.class, MIELE_DEVICE_CLASS_WASHING_MACHINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,8 +59,6 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
|
||||
var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
|
||||
|
||||
WashingMachineChannelSelector selector = (WashingMachineChannelSelector) getValueSelectorFromChannelID(
|
||||
channelID);
|
||||
|
@ -72,9 +69,9 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
|||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
|||
}
|
||||
}
|
||||
// process result
|
||||
if (isResultProcessable(result)) {
|
||||
if (result != null && isResultProcessable(result)) {
|
||||
logger.debug("Result of operation is {}", result.getAsString());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
|
||||
https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="thing-type:miele:appliance">
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>Unique identifier for specific appliance on the gateway.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
|
@ -0,0 +1,107 @@
|
|||
# binding
|
||||
|
||||
binding.miele.name = Miele Binding
|
||||
binding.miele.description = This is the binding for Miele@home appliances
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.miele.coffeemachine.label = Coffee Machine
|
||||
thing-type.miele.coffeemachine.description = This is a Miele@home compatible coffee machine
|
||||
thing-type.miele.dishwasher.label = Dishwasher
|
||||
thing-type.miele.dishwasher.description = This is a Miele@home compatible dishwasher
|
||||
thing-type.miele.fridge.label = Fridge
|
||||
thing-type.miele.fridge.description = This is a Miele@home compatible fridge
|
||||
thing-type.miele.fridgefreezer.label = Fridge Freezer
|
||||
thing-type.miele.fridgefreezer.description = This is a Miele@home compatible fridgefreezer
|
||||
thing-type.miele.hob.label = Hob
|
||||
thing-type.miele.hob.description = This is a Miele@home compatible hob
|
||||
thing-type.miele.hood.label = Hood
|
||||
thing-type.miele.hood.description = This is a Miele@home compatible hood
|
||||
thing-type.miele.oven.label = Oven
|
||||
thing-type.miele.oven.description = This is a Miele@home compatible oven
|
||||
thing-type.miele.tumbledryer.label = Tumbledryer
|
||||
thing-type.miele.tumbledryer.description = This is a Miele@home compatible tumbledryer
|
||||
thing-type.miele.washingmachine.label = Washing Machine
|
||||
thing-type.miele.washingmachine.description = This is a Miele@home compatible washing machine
|
||||
thing-type.miele.xgw3000.label = Miele XGW3000
|
||||
thing-type.miele.xgw3000.description = The Miele bridge represents the Miele@home XGW3000 gateway.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.miele.appliance.uid.label = ID
|
||||
thing-type.config.miele.appliance.uid.description = Unique identifier for specific appliance on the gateway.
|
||||
thing-type.config.miele.xgw3000.interface.label = Network Address of the Multicast Interface
|
||||
thing-type.config.miele.xgw3000.interface.description = Network address of openHAB host interface where the binding will listen for multicast events coming from the Miele@home gateway.
|
||||
thing-type.config.miele.xgw3000.ipAddress.label = Network Address
|
||||
thing-type.config.miele.xgw3000.ipAddress.description = Network address of the Miele@home gateway.
|
||||
thing-type.config.miele.xgw3000.password.label = Password
|
||||
thing-type.config.miele.xgw3000.password.description = Password for the registered Miele@home user.
|
||||
thing-type.config.miele.xgw3000.userName.label = Username
|
||||
thing-type.config.miele.xgw3000.userName.description = Name of a registered Miele@home user.
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.miele.currentTemperature.label = Current Temperature
|
||||
channel-type.miele.currentTemperature.description = Current temperature of the appliance
|
||||
channel-type.miele.door.label = Door
|
||||
channel-type.miele.door.description = Current state of the door of the appliance
|
||||
channel-type.miele.duration.label = Duration
|
||||
channel-type.miele.duration.description = Duration of the program running on the appliance
|
||||
channel-type.miele.duration.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.elapsed.label = Elapsed Time
|
||||
channel-type.miele.elapsed.description = Time elapsed in the program running on the appliance
|
||||
channel-type.miele.elapsed.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.finish.label = Finish Time
|
||||
channel-type.miele.finish.description = Time to finish the program running on the appliance
|
||||
channel-type.miele.finish.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.freezerstate.label = Status
|
||||
channel-type.miele.freezerstate.description = Current status of the freezer compartment
|
||||
channel-type.miele.fridgestate.label = Status
|
||||
channel-type.miele.fridgestate.description = Current status of the fridge compartment
|
||||
channel-type.miele.heat.label = Remaining Heat
|
||||
channel-type.miele.heat.description = Remaining heat level of the heating zone/plate
|
||||
channel-type.miele.phase.label = Phase
|
||||
channel-type.miele.phase.description = Current phase of the program running on the appliance
|
||||
channel-type.miele.plates.label = Plates
|
||||
channel-type.miele.plates.description = Number of heating zones/plates on the hob
|
||||
channel-type.miele.power.label = Power Step
|
||||
channel-type.miele.power.description = Power level of the heating zone/plate
|
||||
channel-type.miele.powerConsumption.label = Power Consumption
|
||||
channel-type.miele.powerConsumption.description = Power consumption by the currently running program on the appliance
|
||||
channel-type.miele.program.label = Program
|
||||
channel-type.miele.program.description = Current program or function running on the appliance
|
||||
channel-type.miele.rawPhase.label = Raw Phase
|
||||
channel-type.miele.rawPhase.description = Current phase of the program running on the appliance as raw number
|
||||
channel-type.miele.rawProgram.label = Raw Program
|
||||
channel-type.miele.rawProgram.description = Current program or function running on the appliance as raw number
|
||||
channel-type.miele.rawState.label = Raw State
|
||||
channel-type.miele.rawState.description = Current status of the appliance as raw number
|
||||
channel-type.miele.spinningspeed.label = Spinning Speed
|
||||
channel-type.miele.spinningspeed.description = Spinning speed in the program running on the appliance
|
||||
channel-type.miele.start.label = Start Time
|
||||
channel-type.miele.start.description = Programmed start time of the program
|
||||
channel-type.miele.start.state.pattern = %1$tH:%1$tM
|
||||
channel-type.miele.state.label = State
|
||||
channel-type.miele.state.description = Current status of the appliance
|
||||
channel-type.miele.step.label = Step
|
||||
channel-type.miele.step.description = Current step in the program running on the appliance
|
||||
channel-type.miele.stop.label = Stop
|
||||
channel-type.miele.stop.description = Stop the appliance
|
||||
channel-type.miele.supercool.label = Super Cool
|
||||
channel-type.miele.supercool.description = Start or stop Super Cooling
|
||||
channel-type.miele.superfreeze.label = Super Freeze
|
||||
channel-type.miele.superfreeze.description = Start or stop Super Freezing
|
||||
channel-type.miele.switch.label = Switch
|
||||
channel-type.miele.switch.description = Switch the appliance on or off
|
||||
channel-type.miele.targetTemperature.label = Target Temperature
|
||||
channel-type.miele.targetTemperature.description = Target temperature to be reached by the appliance
|
||||
channel-type.miele.temperature.label = Temperature
|
||||
channel-type.miele.temperature.description = Temperature reported by the appliance
|
||||
channel-type.miele.time.label = Remaining Time
|
||||
channel-type.miele.time.description = Remaining time of the heating zone/plate
|
||||
channel-type.miele.type.label = Program Type
|
||||
channel-type.miele.type.description = Type of the program running on the appliance
|
||||
channel-type.miele.ventilation.label = Ventilation Power
|
||||
channel-type.miele.ventilation.description = Current ventilation power
|
||||
channel-type.miele.waterConsumption.label = Water Consumption
|
||||
channel-type.miele.waterConsumption.description = Water consumption by the currently running program on the appliance
|
|
@ -0,0 +1,40 @@
|
|||
# binding
|
||||
|
||||
binding.miele.name = Miele Binding
|
||||
binding.miele.description = Dette er bindingen til Miele@home-husholdningsapparater
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.miele.coffeemachine.label = Kaffemaskine
|
||||
thing-type.miele.coffeemachine.description = Dette er en Miele@home-kompatibel kaffemaskine
|
||||
thing-type.miele.dishwasher.label = Opvaskemaskine
|
||||
thing-type.miele.dishwasher.description = Dette er en Miele@home-kompatibel opvaskemaskine
|
||||
thing-type.miele.fridge.label = Køleskab
|
||||
thing-type.miele.fridge.description = Dette er et Miele@home-kompatibelt køleskab
|
||||
thing-type.miele.fridgefreezer.label = Kølefryseskab
|
||||
thing-type.miele.fridgefreezer.description = Dette er et Miele@home-kompatibelt kølefryseskab
|
||||
thing-type.miele.hob.label = Kogeplader
|
||||
thing-type.miele.hob.description = Dette er Miele@home-kompatible kogeplader
|
||||
thing-type.miele.hood.label = Emhætte
|
||||
thing-type.miele.hood.description = Dette er en Miele@home-kompatibel emhætte
|
||||
thing-type.miele.oven.label = Ovn
|
||||
thing-type.miele.oven.description = Dette er en Miele@home-kompatibel ovn
|
||||
thing-type.miele.tumbledryer.label = Tørretumbler
|
||||
thing-type.miele.tumbledryer.description = Dette er en Miele@home-kompatibel tørretumbler
|
||||
thing-type.miele.washingmachine.label = Vaskemaskine
|
||||
thing-type.miele.washingmachine.description = Dette er en Miele@home-kompatibel vaskemaskine
|
||||
thing-type.miele.xgw3000.label = Miele XGW3000
|
||||
thing-type.miele.xgw3000.description = Miele-bridgen repræsenterer Miele@home XGW3000-gateway'en.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.miele.appliance.uid.label = ID
|
||||
thing-type.config.miele.appliance.uid.description = Unik identifikator til specifikt husholdningsapparat på gateway'en.
|
||||
thing-type.config.miele.xgw3000.interface.label = Netværksadresse til multicast-interfacet
|
||||
thing-type.config.miele.xgw3000.interface.description = Netværksadresse til openHAB værts-interfacet hvor bindingen vil lytte på multicast-hændelser fra Miele@home-gateway'en.
|
||||
thing-type.config.miele.xgw3000.ipAddress.label = Netværksadresse
|
||||
thing-type.config.miele.xgw3000.ipAddress.description = Netværksadresse til Miele@home-gateway'en.
|
||||
thing-type.config.miele.xgw3000.password.label = Adgangskode
|
||||
thing-type.config.miele.xgw3000.password.description = Adgangskode til registreret Miele@home-bruger.
|
||||
thing-type.config.miele.xgw3000.userName.label = Brugernavn
|
||||
thing-type.config.miele.xgw3000.userName.description = Navn på en registeret Miele@home-bruger.
|
|
@ -27,12 +27,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -32,13 +32,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -29,13 +29,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -38,13 +38,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -38,13 +38,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -23,12 +23,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies the appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -47,13 +47,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -32,13 +32,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
|
||||
|
|
|
@ -38,12 +38,7 @@
|
|||
|
||||
<representation-property>uid</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="uid" type="text" required="true">
|
||||
<label>ID</label>
|
||||
<description>The identifier identifies one certain appliance on the ZigBee network.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
<config-description-ref uri="thing-type:miele:appliance"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<!-- Miele Bridge -->
|
||||
<bridge-type id="xgw3000">
|
||||
<label>Miele XGW3000</label>
|
||||
<description>The miele bridge represents the Miele@home XGW3000 gateway.</description>
|
||||
<description>The Miele bridge represents the Miele@home XGW3000 gateway.</description>
|
||||
|
||||
<properties>
|
||||
<property name="vendor">Miele</property>
|
||||
|
@ -25,7 +25,7 @@
|
|||
<context>network-address</context>
|
||||
<label>Network Address of the Multicast Interface</label>
|
||||
<description>Network address of openHAB host interface where the binding will listen for multicast events coming
|
||||
from the Miele@home gateway</description>
|
||||
from the Miele@home gateway.</description>
|
||||
</parameter>
|
||||
<parameter name="userName" type="text" required="false">
|
||||
<label>Username</label>
|
||||
|
@ -36,7 +36,7 @@
|
|||
<parameter name="password" type="text" required="false">
|
||||
<context>password</context>
|
||||
<label>Password</label>
|
||||
<description>Password for the registered Miele@home</description>
|
||||
<description>Password for the registered Miele@home user.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
|
|
@ -22,17 +22,16 @@ import org.openhab.core.types.UnDefType;
|
|||
|
||||
/**
|
||||
* This class provides test cases for {@link
|
||||
* org.openhab.binding.miele.internal.ExtendedDeviceStateUtil}
|
||||
* org.openhab.binding.miele.internal.DeviceUtil}
|
||||
*
|
||||
* @author Jacob Laursen - Added power/water consumption channels
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
|
||||
public class ExtendedDeviceStateUtilTest extends JavaTest {
|
||||
public class DeviceUtilTest extends JavaTest {
|
||||
|
||||
@Test
|
||||
public void bytesToHexWhenTopBitIsUsedReturnsCorrectString() {
|
||||
String actual = ExtendedDeviceStateUtil
|
||||
.bytesToHex(new byte[] { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef });
|
||||
String actual = DeviceUtil.bytesToHex(new byte[] { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef });
|
||||
assertEquals("DEADBEEF", actual);
|
||||
}
|
||||
|
||||
|
@ -45,27 +44,27 @@ public class ExtendedDeviceStateUtilTest extends JavaTest {
|
|||
@Test
|
||||
public void stringToBytesWhenTopBitIsUsedReturnsSingleByte() {
|
||||
byte[] expected = new byte[] { (byte) 0x00, (byte) 0x80, (byte) 0x00 };
|
||||
byte[] actual = ExtendedDeviceStateUtil.stringToBytes("\u0000\u0080\u0000");
|
||||
byte[] actual = DeviceUtil.stringToBytes("\u0000\u0080\u0000");
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemperatureStateWellFormedValueReturnsQuantityType() throws NumberFormatException {
|
||||
assertEquals(new QuantityType<>(42, SIUnits.CELSIUS), ExtendedDeviceStateUtil.getTemperatureState("42"));
|
||||
assertEquals(new QuantityType<>(42, SIUnits.CELSIUS), DeviceUtil.getTemperatureState("42"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemperatureStateMagicValueReturnsUndefined() throws NumberFormatException {
|
||||
assertEquals(UnDefType.UNDEF, ExtendedDeviceStateUtil.getTemperatureState("32768"));
|
||||
assertEquals(UnDefType.UNDEF, DeviceUtil.getTemperatureState("32768"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemperatureStateNonNumericValueThrowsNumberFormatException() {
|
||||
assertThrows(NumberFormatException.class, () -> ExtendedDeviceStateUtil.getTemperatureState("A"));
|
||||
assertThrows(NumberFormatException.class, () -> DeviceUtil.getTemperatureState("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemperatureStateNullValueThrowsNumberFormatException() {
|
||||
assertThrows(NumberFormatException.class, () -> ExtendedDeviceStateUtil.getTemperatureState(null));
|
||||
assertThrows(NumberFormatException.class, () -> DeviceUtil.getTemperatureState(null));
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import org.openhab.core.test.java.JavaTest;
|
|||
* This class provides test cases for {@link
|
||||
* org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier}
|
||||
*
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
public class FullyQualifiedApplianceIdentifierTest extends JavaTest {
|
||||
|
||||
|
|
Loading…
Reference in New Issue