[miele] Add null annotations and improve error handling robustness (#12497)
* Add null annotations and improve error handling robustness * Fix compliancy with rule ConstantNameCheck Fixes #12496 Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
parent
7c29e4d565
commit
f21bbc5945
|
@ -17,6 +17,9 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
|
@ -29,13 +32,14 @@ import org.openhab.core.types.UnDefType;
|
|||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DeviceUtil {
|
||||
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||
private static final String TEMPERATURE_UNDEFINED = "32768";
|
||||
private static final String TEMPERATURE_COLD = "-32760";
|
||||
private static final String TEXT_PREFIX = "miele.";
|
||||
|
||||
private static final Map<String, String> states = Map.ofEntries(Map.entry("1", "off"), Map.entry("2", "stand-by"),
|
||||
private static final Map<String, String> STATES = Map.ofEntries(Map.entry("1", "off"), Map.entry("2", "stand-by"),
|
||||
Map.entry("3", "programmed"), Map.entry("4", "waiting-to-start"), Map.entry("5", "running"),
|
||||
Map.entry("6", "paused"), Map.entry("7", "end"), Map.entry("8", "failure"), Map.entry("9", "abort"),
|
||||
Map.entry("10", "idle"), Map.entry("11", "rinse-hold"), Map.entry("12", "service"),
|
||||
|
@ -84,8 +88,9 @@ public class DeviceUtil {
|
|||
* Get state text for provided string taking into consideration {@link DeviceMetaData}
|
||||
* as well as built-in/translated strings.
|
||||
*/
|
||||
public static State getStateTextState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
return getTextState(s, dmd, translationProvider, states, MISSING_STATE_TEXT_PREFIX, "");
|
||||
public static State getStateTextState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTextState(s, dmd, translationProvider, STATES, MISSING_STATE_TEXT_PREFIX, "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,8 +105,9 @@ public class DeviceUtil {
|
|||
* @param appliancePrefix Appliance prefix appended to text key (including dot)
|
||||
* @return Text string as State
|
||||
*/
|
||||
public static State getTextState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider,
|
||||
Map<String, String> valueMap, String propertyPrefix, String appliancePrefix) {
|
||||
public static State getTextState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider, Map<String, String> valueMap, String propertyPrefix,
|
||||
String appliancePrefix) {
|
||||
if ("0".equals(s)) {
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
@ -116,7 +122,7 @@ public class DeviceUtil {
|
|||
}
|
||||
|
||||
String value = valueMap.get(s);
|
||||
if (value != null) {
|
||||
if (value != null && translationProvider != null) {
|
||||
String key = TEXT_PREFIX + propertyPrefix + appliancePrefix + value;
|
||||
return new StringType(
|
||||
translationProvider.getText(key, gatewayText != null ? gatewayText : propertyPrefix + s));
|
||||
|
|
|
@ -12,12 +12,15 @@
|
|||
*/
|
||||
package org.openhab.binding.miele.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link FullyQualifiedApplianceIdentifier} class represents a fully qualified appliance identifier.
|
||||
* Example: "hdm:ZigBee:0123456789abcdef#210"
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FullyQualifiedApplianceIdentifier {
|
||||
private String uid;
|
||||
private String protocol;
|
||||
|
@ -56,7 +59,7 @@ public class FullyQualifiedApplianceIdentifier {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return Protocol prefix of fully qualified appliance identifier (e.g. "hdmi:ZigBee:"")
|
||||
* @return Protocol prefix of fully qualified appliance identifier (e.g. "hdmi:ZigBee:")
|
||||
*/
|
||||
public String getProtocol() {
|
||||
return this.protocol;
|
||||
|
|
|
@ -28,6 +28,7 @@ public class MieleBindingConstants {
|
|||
|
||||
public static final String BINDING_ID = "miele";
|
||||
public static final String APPLIANCE_ID = "uid";
|
||||
public static final String MIELE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.Miele";
|
||||
|
||||
// Properties
|
||||
public static final String PROPERTY_DEVICE_CLASS = "deviceClass";
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.discovery.MieleApplianceDiscoveryService;
|
||||
import org.openhab.binding.miele.internal.handler.CoffeeMachineHandler;
|
||||
import org.openhab.binding.miele.internal.handler.DishWasherHandler;
|
||||
|
@ -56,6 +58,7 @@ import org.osgi.service.component.annotations.Reference;
|
|||
*
|
||||
* @author Karel Goderis - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.miele")
|
||||
public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
|
@ -82,8 +85,8 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID,
|
||||
ThingUID bridgeUID) {
|
||||
public @Nullable Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration,
|
||||
@Nullable ThingUID thingUID, @Nullable ThingUID bridgeUID) {
|
||||
if (MieleBridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
ThingUID mieleBridgeUID = getBridgeThingUID(thingTypeUID, thingUID, configuration);
|
||||
return super.createThing(thingTypeUID, configuration, mieleBridgeUID, null);
|
||||
|
@ -97,7 +100,7 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
if (MieleBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||
MieleBridgeHandler handler = new MieleBridgeHandler((Bridge) thing);
|
||||
registerApplianceDiscoveryService(handler);
|
||||
|
@ -135,7 +138,8 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
|||
return null;
|
||||
}
|
||||
|
||||
private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
|
||||
private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, @Nullable ThingUID thingUID,
|
||||
Configuration configuration) {
|
||||
if (thingUID == null) {
|
||||
String hostID = (String) configuration.get(HOST);
|
||||
thingUID = new ThingUID(thingTypeUID, hostID);
|
||||
|
@ -143,12 +147,16 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory {
|
|||
return thingUID;
|
||||
}
|
||||
|
||||
private ThingUID getApplianceUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
private ThingUID getApplianceUID(ThingTypeUID thingTypeUID, @Nullable ThingUID thingUID,
|
||||
Configuration configuration, @Nullable ThingUID bridgeUID) {
|
||||
String applianceId = (String) configuration.get(APPLIANCE_ID);
|
||||
|
||||
if (thingUID == null) {
|
||||
thingUID = new ThingUID(thingTypeUID, applianceId, bridgeUID.getId());
|
||||
if (bridgeUID == null) {
|
||||
thingUID = new ThingUID(thingTypeUID, applianceId);
|
||||
} else {
|
||||
thingUID = new ThingUID(thingTypeUID, bridgeUID, applianceId);
|
||||
}
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.miele.internal.api.dto;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
||||
/**
|
||||
* The {@link DeviceClassObject} class represents the DeviceClassObject node in the response JSON.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
**/
|
||||
public class DeviceClassObject {
|
||||
public String DeviceClassType;
|
||||
public JsonArray Operations;
|
||||
public String DeviceClass;
|
||||
public JsonArray Properties;
|
||||
|
||||
public DeviceClassObject() {
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.miele.internal;
|
||||
package org.openhab.binding.miele.internal.api.dto;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.miele.internal.api.dto;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link DeviceProperty} class represents the DeviceProperty node in the response JSON.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
**/
|
||||
public class DeviceProperty {
|
||||
public String Name;
|
||||
public String Value;
|
||||
public int Polling;
|
||||
public JsonObject Metadata;
|
||||
|
||||
public DeviceProperty() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.miele.internal.api.dto;
|
||||
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.binding.miele.internal.MieleBindingConstants;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link HomeDevice} class represents the HomeDevice node in the response JSON.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
**/
|
||||
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;
|
||||
public String ProtocolAdapterName;
|
||||
public String Vendor;
|
||||
public String UID;
|
||||
public String Type;
|
||||
public JsonArray DeviceClasses;
|
||||
public String Version;
|
||||
public String TimestampAdded;
|
||||
public JsonObject Error;
|
||||
public JsonObject Properties;
|
||||
|
||||
public HomeDevice() {
|
||||
}
|
||||
|
||||
public FullyQualifiedApplianceIdentifier getApplianceIdentifier() {
|
||||
return new FullyQualifiedApplianceIdentifier(this.UID);
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return Properties.get("serial.number").getAsString();
|
||||
}
|
||||
|
||||
public String getFirmwareVersion() {
|
||||
return Properties.get("firmware.version").getAsString();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public String getConnectionBaudRate() {
|
||||
JsonElement baudRate = Properties.get("connection.baud.rate");
|
||||
if (baudRate == null) {
|
||||
return null;
|
||||
}
|
||||
return baudRate.getAsString();
|
||||
}
|
||||
|
||||
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(MieleBindingConstants.MIELE_CLASS) && !dcStr.equals(MIELE_APPLIANCE_CLASS)) {
|
||||
return dcStr.substring(MieleBindingConstants.MIELE_CLASS.length());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -20,13 +20,15 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.api.dto.HomeDevice;
|
||||
import org.openhab.binding.miele.internal.handler.ApplianceStatusListener;
|
||||
import org.openhab.binding.miele.internal.handler.MieleApplianceHandler;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
|
@ -44,6 +46,7 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Martin Lepsy - Added protocol information in order so support WiFi devices
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements ApplianceStatusListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MieleApplianceDiscoveryService.class);
|
||||
|
@ -75,10 +78,8 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
|
|||
@Override
|
||||
public void startScan() {
|
||||
List<HomeDevice> appliances = mieleBridgeHandler.getHomeDevices();
|
||||
if (appliances != null) {
|
||||
for (HomeDevice l : appliances) {
|
||||
onApplianceAddedInternal(l);
|
||||
}
|
||||
for (HomeDevice l : appliances) {
|
||||
onApplianceAddedInternal(l);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,11 +101,17 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
|
|||
Map<String, Object> properties = new HashMap<>(9);
|
||||
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
|
||||
properties.put(Thing.PROPERTY_VENDOR, appliance.Vendor);
|
||||
String vendor = appliance.Vendor;
|
||||
if (vendor != null) {
|
||||
properties.put(Thing.PROPERTY_VENDOR, vendor);
|
||||
}
|
||||
properties.put(Thing.PROPERTY_MODEL_ID, appliance.getApplianceModel());
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, appliance.getSerialNumber());
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, appliance.getFirmwareVersion());
|
||||
properties.put(PROPERTY_PROTOCOL_ADAPTER, appliance.ProtocolAdapterName);
|
||||
String protocolAdapterName = appliance.ProtocolAdapterName;
|
||||
if (protocolAdapterName != null) {
|
||||
properties.put(PROPERTY_PROTOCOL_ADAPTER, protocolAdapterName);
|
||||
}
|
||||
properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId());
|
||||
String deviceClass = appliance.getDeviceClass();
|
||||
if (deviceClass != null) {
|
||||
|
@ -149,7 +156,7 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
|
|||
// nothing to do
|
||||
}
|
||||
|
||||
private ThingUID getThingUID(HomeDevice appliance) {
|
||||
private @Nullable ThingUID getThingUID(HomeDevice appliance) {
|
||||
ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
|
||||
String modelId = appliance.getDeviceClass();
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2022 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.miele.internal.exceptions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link MieleRpcException} indicates failure to perform JSON-RPC call.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class MieleRpcException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = -8147063891196639054L;
|
||||
|
||||
public MieleRpcException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MieleRpcException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
|
@ -12,8 +12,10 @@
|
|||
*/
|
||||
package org.openhab.binding.miele.internal.handler;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
/**
|
||||
|
@ -25,6 +27,7 @@ import org.openhab.core.types.State;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Jacob Laursen - Added power/water consumption channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ApplianceChannelSelector {
|
||||
|
||||
@Override
|
||||
|
@ -61,7 +64,7 @@ public interface ApplianceChannelSelector {
|
|||
* @param dmd - the device meta data
|
||||
* @param translationProvider {@link MieleTranslationProvider} instance
|
||||
*/
|
||||
State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider);
|
||||
State getState(String s, @Nullable DeviceMetaData dmd, @Nullable MieleTranslationProvider translationProvider);
|
||||
|
||||
/**
|
||||
* Returns a State for the given string, taking into
|
||||
|
@ -71,7 +74,7 @@ public interface ApplianceChannelSelector {
|
|||
* @param s - the value to be used to instantiate the State
|
||||
* @param dmd - the device meta data
|
||||
*/
|
||||
State getState(String s, DeviceMetaData dmd);
|
||||
State getState(String s, @Nullable DeviceMetaData dmd);
|
||||
|
||||
/**
|
||||
* Returns a raw State for the given string, not taking into
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
*/
|
||||
package org.openhab.binding.miele.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.api.dto.HomeDevice;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -25,6 +26,7 @@ import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ApplianceStatusListener {
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,12 +15,13 @@ package org.openhab.binding.miele.internal.handler;
|
|||
import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
|
@ -37,50 +38,43 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Stephan Esch - Initial contribution
|
||||
* @author Jacob Laursen - Added raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, programs, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PROGRAMS, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
MIELE_COFFEE_MACHINE_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM("", PROGRAM_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAMTYPE("programType", "type", StringType.class, false),
|
||||
PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PHASES, MISSING_PHASE_TEXT_PREFIX,
|
||||
MIELE_COFFEE_MACHINE_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false),
|
||||
// lightingStatus signalFailure signalInfo
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -92,13 +86,13 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
SWITCH(null, "switch", OnOffType.class, false);
|
||||
SWITCH("", "switch", OnOffType.class, false);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CoffeeMachineChannelSelector.class);
|
||||
|
||||
private static final Map<String, String> programs = Collections.<String, String> emptyMap();
|
||||
private static final Map<String, String> PROGRAMS = Map.of();
|
||||
|
||||
private static final Map<String, String> phases = Collections.<String, String> emptyMap();
|
||||
private static final Map<String, String> PHASES = Map.of();
|
||||
|
||||
private final String mieleID;
|
||||
private final String channelID;
|
||||
|
@ -139,12 +133,13 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -171,6 +166,6 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,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.MIELE_DEVICE_CLASS_COFFEE_SYSTEM;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -35,6 +37,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CoffeeMachineHandler.class);
|
||||
|
@ -50,26 +53,33 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
CoffeeMachineChannelSelector selector = (CoffeeMachineChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOn");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOff");
|
||||
}
|
||||
break;
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOn");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOff");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +91,14 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.WATER_CON
|
|||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -42,6 +44,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN), added power/water consumption channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSelector>
|
||||
implements ExtendedDeviceStateListener {
|
||||
|
||||
|
@ -61,26 +64,33 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
DishwasherChannelSelector selector = (DishwasherChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +102,14 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,11 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -43,48 +45,41 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Kai Kreuzer - Changed START_TIME to DateTimeType
|
||||
* @author Jacob Laursen - Added power/water consumption channels, raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true, false),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true, false),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, programs, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PROGRAMS, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
MIELE_DISHWASHER_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM("", PROGRAM_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PHASES, MISSING_PHASE_TEXT_PREFIX,
|
||||
MIELE_DISHWASHER_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -98,7 +93,8 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DURATION("duration", "duration", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -112,7 +108,8 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -126,7 +123,8 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -140,7 +138,8 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -152,7 +151,7 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
SWITCH(null, "switch", OnOffType.class, false, false),
|
||||
SWITCH("", "switch", OnOffType.class, false, false),
|
||||
POWER_CONSUMPTION(EXTENDED_DEVICE_STATE_PROPERTY_NAME, POWER_CONSUMPTION_CHANNEL_ID, QuantityType.class, false,
|
||||
true),
|
||||
WATER_CONSUMPTION(EXTENDED_DEVICE_STATE_PROPERTY_NAME, WATER_CONSUMPTION_CHANNEL_ID, QuantityType.class, false,
|
||||
|
@ -160,12 +159,12 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(DishwasherChannelSelector.class);
|
||||
|
||||
private static final Map<String, String> programs = Map.ofEntries(entry("26", "intensive"),
|
||||
private static final Map<String, String> PROGRAMS = Map.ofEntries(entry("26", "intensive"),
|
||||
entry("27", "maintenance-programme"), entry("28", "eco"), entry("30", "normal"), entry("32", "automatic"),
|
||||
entry("34", "solarsave"), entry("35", "gentle"), entry("36", "extra-quiet"), entry("37", "hygiene"),
|
||||
entry("38", "quickpowerwash"), entry("42", "tall-items"));
|
||||
|
||||
private static final 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;
|
||||
|
@ -209,12 +208,13 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -241,6 +241,6 @@ public enum DishwasherChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,12 +12,15 @@
|
|||
*/
|
||||
package org.openhab.binding.miele.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Appliance handlers can implement the {@link ExtendedDeviceStateListener} interface
|
||||
* to extract additional information from the ExtendedDeviceState property.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ExtendedDeviceStateListener {
|
||||
void onApplianceExtendedStateChanged(byte[] extendedDeviceState);
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
|
@ -36,38 +38,39 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Jacob Laursen - Added UoM for temperatures, raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FridgeChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
SUPERCOOL("", SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
|
||||
FRIDGECURRENTTEMP("currentTemperature", "current", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
FRIDGETARGETTEMP("targetTemperature", "target", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false) {
|
||||
@Override
|
||||
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -79,7 +82,7 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
START(null, "start", OnOffType.class, false);
|
||||
START("", "start", OnOffType.class, false);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FridgeChannelSelector.class);
|
||||
|
||||
|
@ -121,12 +124,13 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -153,7 +157,7 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
public State getTemperatureState(String s) {
|
||||
|
|
|
@ -16,9 +16,11 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
|
@ -37,53 +39,55 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Jacob Laursen - Added UoM for temperatures, raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
FREEZERSTATE("freezerState", "freezerstate", StringType.class, false),
|
||||
FRIDGESTATE("fridgeState", "fridgestate", StringType.class, false),
|
||||
SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
|
||||
SUPERFREEZE(null, SUPERFREEZE_CHANNEL_ID, OnOffType.class, false),
|
||||
SUPERCOOL("", SUPERCOOL_CHANNEL_ID, OnOffType.class, false),
|
||||
SUPERFREEZE("", SUPERFREEZE_CHANNEL_ID, OnOffType.class, false),
|
||||
FREEZERCURRENTTEMP("freezerCurrentTemperature", "freezercurrent", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
FREEZERTARGETTEMP("freezerTargetTemperature", "freezertarget", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
FRIDGECURRENTTEMP("fridgeCurrentTemperature", "fridgecurrent", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
FRIDGETARGETTEMP("fridgeTargetTemperature", "fridgetarget", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false) {
|
||||
@Override
|
||||
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -95,7 +99,7 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
START(null, "start", OnOffType.class, false);
|
||||
START("", "start", OnOffType.class, false);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FridgeFreezerChannelSelector.class);
|
||||
|
||||
|
@ -138,12 +142,13 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -170,7 +175,7 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
public State getTemperatureState(String s) {
|
||||
|
|
|
@ -14,7 +14,9 @@ package org.openhab.binding.miele.internal.handler;
|
|||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
||||
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -35,6 +37,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FridgeFreezerHandler.class);
|
||||
|
@ -50,33 +53,39 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
FridgeFreezerChannelSelector selector = (FridgeFreezerChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SUPERCOOL: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperCooling");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperCooling");
|
||||
}
|
||||
break;
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
switch (selector) {
|
||||
case SUPERCOOL: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperCooling");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperCooling");
|
||||
}
|
||||
case SUPERFREEZE: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperFreezing");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperFreezing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
break;
|
||||
}
|
||||
case SUPERFREEZE: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperFreezing");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperFreezing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.debug("{} is a read-only channel that does not accept commands", selector.getChannelID());
|
||||
}
|
||||
}
|
||||
// process result
|
||||
|
@ -87,6 +96,14 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@ package org.openhab.binding.miele.internal.handler;
|
|||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
||||
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -36,6 +38,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FridgeHandler.class);
|
||||
|
@ -50,32 +53,39 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
FridgeChannelSelector selector = (FridgeChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SUPERCOOL: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperCooling");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperCooling");
|
||||
}
|
||||
break;
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
switch (selector) {
|
||||
case SUPERCOOL: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startSuperCooling");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopSuperCooling");
|
||||
}
|
||||
case START: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case START: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +97,14 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,16 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.Type;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -32,26 +35,25 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Jacob Laursen - Added raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum HobChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PLATES("plateNumbers", "plates", DecimalType.class, true),
|
||||
PLATE1_POWER("plate1PowerStep", "plate1power", DecimalType.class, false),
|
||||
PLATE1_HEAT("plate1RemainingHeat", "plate1heat", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
// If there is remaining heat, the device metadata contains some informative string which can not be
|
||||
// converted into a DecimalType. We therefore ignore the metadata and return the device property value as a
|
||||
// State
|
||||
|
@ -62,7 +64,8 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
PLATE2_POWER("plate2PowerStep", "plate2power", DecimalType.class, false),
|
||||
PLATE2_HEAT("plate2RemainingHeat", "plate2heat", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getState(s);
|
||||
}
|
||||
},
|
||||
|
@ -70,7 +73,8 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
PLATE3_POWER("plate3PowerStep", "plate3power", DecimalType.class, false),
|
||||
PLATE3_HEAT("plate3RemainingHeat", "plate3heat", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getState(s);
|
||||
}
|
||||
},
|
||||
|
@ -78,7 +82,8 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
PLATE4_POWER("plate4PowerStep", "plate4power", DecimalType.class, false),
|
||||
PLATE4_HEAT("plate4RemainingHeat", "plate4heat", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getState(s);
|
||||
}
|
||||
},
|
||||
|
@ -86,7 +91,8 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
PLATE5_POWER("plate5PowerStep", "plate5power", DecimalType.class, false),
|
||||
PLATE5_HEAT("plate5RemainingHeat", "plate5heat", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getState(s);
|
||||
}
|
||||
},
|
||||
|
@ -94,7 +100,8 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
PLATE6_POWER("plate6PowerStep", "plate6power", DecimalType.class, false),
|
||||
PLATE6_HEAT("plate6RemainingHeat", "plate6heat", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getState(s);
|
||||
}
|
||||
},
|
||||
|
@ -140,12 +147,13 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -172,6 +180,6 @@ public enum HobChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.openhab.binding.miele.internal.handler;
|
|||
|
||||
import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_HOB;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
|
@ -27,6 +28,7 @@ import org.openhab.core.types.Command;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Kai Kreuzer - fixed handling of REFRESH commands
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HobHandler extends MieleApplianceHandler<HobChannelSelector> {
|
||||
|
||||
public HobHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) {
|
||||
|
|
|
@ -16,9 +16,11 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
@ -34,26 +36,25 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Karel Goderis - Initial contribution
|
||||
* @author Jacob Laursen - Added raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum HoodChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
VENTILATION("ventilationPower", "ventilation", DecimalType.class, false),
|
||||
LIGHT("lightingStatus", "light", OnOffType.class, false) {
|
||||
@Override
|
||||
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("ON");
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ public enum HoodChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
STOP(null, "stop", OnOffType.class, false);
|
||||
STOP("", "stop", OnOffType.class, false);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HoodChannelSelector.class);
|
||||
|
||||
|
@ -107,12 +108,13 @@ public enum HoodChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -139,6 +141,6 @@ public enum HoodChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,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.MIELE_DEVICE_CLASS_HOOD;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -35,6 +37,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
**/
|
||||
@NonNullByDefault
|
||||
public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HoodHandler.class);
|
||||
|
@ -49,31 +52,37 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
HoodChannelSelector selector = (HoodChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case LIGHT: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startLighting");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopLighting");
|
||||
}
|
||||
break;
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
switch (selector) {
|
||||
case LIGHT: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "startLighting");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stopLighting");
|
||||
}
|
||||
case STOP: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
break;
|
||||
}
|
||||
case STOP: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.debug("{} is a read-only channel that does not accept commands", selector.getChannelID());
|
||||
}
|
||||
}
|
||||
// process result
|
||||
|
@ -84,6 +93,14 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,17 +19,16 @@ import java.util.IllformedLocaleException;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.api.dto.HomeDevice;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
|
@ -43,11 +42,11 @@ import org.openhab.core.thing.binding.ThingHandler;
|
|||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
@ -62,23 +61,23 @@ import com.google.gson.JsonParser;
|
|||
* @author Martin Lepsy - Added check for JsonNull result
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannelSelector> extends BaseThingHandler
|
||||
implements ApplianceStatusListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(MieleApplianceHandler.class);
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Stream
|
||||
.of(THING_TYPE_DISHWASHER, THING_TYPE_OVEN, THING_TYPE_FRIDGE, THING_TYPE_DRYER, THING_TYPE_HOB,
|
||||
THING_TYPE_FRIDGEFREEZER, THING_TYPE_HOOD, THING_TYPE_WASHINGMACHINE, THING_TYPE_COFFEEMACHINE)
|
||||
.collect(Collectors.toSet());
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_DISHWASHER, THING_TYPE_OVEN,
|
||||
THING_TYPE_FRIDGE, THING_TYPE_DRYER, THING_TYPE_HOB, THING_TYPE_FRIDGEFREEZER, THING_TYPE_HOOD,
|
||||
THING_TYPE_WASHINGMACHINE, THING_TYPE_COFFEEMACHINE);
|
||||
|
||||
protected Gson gson = new Gson();
|
||||
|
||||
protected String applianceId;
|
||||
protected MieleBridgeHandler bridgeHandler;
|
||||
protected @Nullable String applianceId;
|
||||
protected @Nullable MieleBridgeHandler bridgeHandler;
|
||||
protected TranslationProvider i18nProvider;
|
||||
protected LocaleProvider localeProvider;
|
||||
protected MieleTranslationProvider translationProvider;
|
||||
protected @Nullable MieleTranslationProvider translationProvider;
|
||||
private Class<E> selectorType;
|
||||
protected String modelID;
|
||||
|
||||
|
@ -101,7 +100,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
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)) {
|
||||
if (c.getChannelID().equals(valueSelectorText)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +116,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
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)) {
|
||||
if (!c.getMieleID().isEmpty() && c.getMieleID().equals(valueSelectorText)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +167,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
if (applianceId != null) {
|
||||
MieleBridgeHandler bridgeHandler = getMieleBridgeHandler();
|
||||
if (bridgeHandler != null) {
|
||||
getMieleBridgeHandler().unregisterApplianceStatusListener(this);
|
||||
bridgeHandler.unregisterApplianceStatusListener(this);
|
||||
}
|
||||
applianceId = null;
|
||||
}
|
||||
|
@ -186,12 +185,17 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
@Override
|
||||
public void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applicationIdentifier,
|
||||
DeviceClassObject dco) {
|
||||
String myApplianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (myApplianceId == null || !myApplianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
String applianceId = this.applianceId;
|
||||
if (applianceId == null || !applianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (JsonElement prop : dco.Properties.getAsJsonArray()) {
|
||||
JsonArray properties = dco.Properties;
|
||||
if (properties == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (JsonElement prop : properties.getAsJsonArray()) {
|
||||
try {
|
||||
DeviceProperty dp = gson.fromJson(prop, DeviceProperty.class);
|
||||
if (dp == null) {
|
||||
|
@ -210,9 +214,9 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
|
||||
@Override
|
||||
public void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applicationIdentifier, DeviceProperty dp) {
|
||||
String myApplianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
String applianceId = this.applianceId;
|
||||
|
||||
if (myApplianceId == null || !myApplianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
if (applianceId == null || !applianceId.equals(applicationIdentifier.getApplianceId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -225,8 +229,8 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
if (dp.Metadata == null) {
|
||||
String metadata = metaDataCache.get(new StringBuilder().append(dp.Name).toString().trim());
|
||||
if (metadata != null) {
|
||||
JsonObject jsonMetaData = (JsonObject) JsonParser.parseString(metadata);
|
||||
dmd = gson.fromJson(jsonMetaData, DeviceMetaData.class);
|
||||
JsonObject jsonMetadata = (JsonObject) JsonParser.parseString(metadata);
|
||||
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
|
||||
if (dmd != null) {
|
||||
|
@ -237,8 +241,9 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
}
|
||||
}
|
||||
}
|
||||
if (dp.Metadata != null) {
|
||||
String metadata = dp.Metadata.toString().replace("enum", "MieleEnum");
|
||||
JsonObject jsonMetadata = dp.Metadata;
|
||||
if (jsonMetadata != null) {
|
||||
String metadata = jsonMetadata.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);
|
||||
|
@ -269,19 +274,14 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
if (!selector.isProperty()) {
|
||||
ChannelUID theChannelUID = new ChannelUID(getThing().getUID(), selector.getChannelID());
|
||||
|
||||
if (dp.Value != null) {
|
||||
State state = selector.getState(dpValue, dmd, this.translationProvider);
|
||||
logger.trace("Update state of {} with getState '{}'", theChannelUID, state);
|
||||
updateState(theChannelUID, state);
|
||||
updateRawChannel(dp.Name, dpValue);
|
||||
} else {
|
||||
updateState(theChannelUID, UnDefType.UNDEF);
|
||||
}
|
||||
State state = selector.getState(dpValue, dmd, this.translationProvider);
|
||||
logger.trace("Update state of {} with getState '{}'", theChannelUID, state);
|
||||
updateState(theChannelUID, state);
|
||||
updateRawChannel(dp.Name, dpValue);
|
||||
} else {
|
||||
logger.debug("Updating the property '{}' of '{}' to '{}'", selector.getChannelID(),
|
||||
getThing().getUID(), selector.getState(dpValue, dmd, this.translationProvider).toString());
|
||||
@NonNull
|
||||
Map<@NonNull String, @NonNull String> properties = editProperties();
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(selector.getChannelID(),
|
||||
selector.getState(dpValue, dmd, this.translationProvider).toString());
|
||||
updateProperties(properties);
|
||||
|
@ -330,31 +330,46 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
|
||||
@Override
|
||||
public void onApplianceRemoved(HomeDevice appliance) {
|
||||
String applianceId = this.applianceId;
|
||||
if (applianceId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (applianceId.equals(appliance.getApplianceIdentifier().getApplianceId())) {
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
|
||||
if (applianceIdentifier == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (applianceId.equals(applianceIdentifier.getApplianceId())) {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplianceAdded(HomeDevice appliance) {
|
||||
String applianceId = this.applianceId;
|
||||
if (applianceId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
|
||||
if (applianceIdentifier == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (applianceId.equals(applianceIdentifier.getApplianceId())) {
|
||||
@NonNull
|
||||
Map<@NonNull String, @NonNull String> properties = editProperties();
|
||||
properties.put(Thing.PROPERTY_VENDOR, appliance.Vendor);
|
||||
Map<String, String> properties = editProperties();
|
||||
String vendor = appliance.Vendor;
|
||||
if (vendor != null) {
|
||||
properties.put(Thing.PROPERTY_VENDOR, vendor);
|
||||
}
|
||||
properties.put(Thing.PROPERTY_MODEL_ID, appliance.getApplianceModel());
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, appliance.getSerialNumber());
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, appliance.getFirmwareVersion());
|
||||
properties.put(PROPERTY_PROTOCOL_ADAPTER, appliance.ProtocolAdapterName);
|
||||
String protocolAdapterName = appliance.ProtocolAdapterName;
|
||||
if (protocolAdapterName != null) {
|
||||
properties.put(PROPERTY_PROTOCOL_ADAPTER, protocolAdapterName);
|
||||
}
|
||||
String deviceClass = appliance.getDeviceClass();
|
||||
if (deviceClass != null) {
|
||||
properties.put(PROPERTY_DEVICE_CLASS, deviceClass);
|
||||
|
@ -372,7 +387,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized MieleBridgeHandler getMieleBridgeHandler() {
|
||||
private synchronized @Nullable MieleBridgeHandler getMieleBridgeHandler() {
|
||||
if (this.bridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
|
@ -380,8 +395,9 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
if (handler instanceof MieleBridgeHandler) {
|
||||
this.bridgeHandler = (MieleBridgeHandler) handler;
|
||||
this.bridgeHandler.registerApplianceStatusListener(this);
|
||||
var bridgeHandler = (MieleBridgeHandler) handler;
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
bridgeHandler.registerApplianceStatusListener(this);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -390,9 +406,6 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
|
|||
}
|
||||
|
||||
protected boolean isResultProcessable(JsonElement result) {
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Provided result is null");
|
||||
}
|
||||
return !result.isJsonNull();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import java.net.URL;
|
|||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.IllformedLocaleException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -49,8 +48,13 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceClassObject;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
|
||||
import org.openhab.binding.miele.internal.api.dto.HomeDevice;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.common.NamedThreadFactory;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
|
@ -69,6 +73,7 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
|
@ -80,12 +85,10 @@ import com.google.gson.JsonParser;
|
|||
* @author Martin Lepsy - Added protocol information to support WiFi devices & some refactoring for HomeDevice
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
**/
|
||||
@NonNullByDefault
|
||||
public class MieleBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
@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";
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_XGW3000);
|
||||
|
||||
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])$");
|
||||
|
@ -102,128 +105,14 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
private final Logger logger = LoggerFactory.getLogger(MieleBridgeHandler.class);
|
||||
|
||||
protected List<ApplianceStatusListener> applianceStatusListeners = new CopyOnWriteArrayList<>();
|
||||
protected ScheduledFuture<?> pollingJob;
|
||||
protected ExecutorService executor;
|
||||
protected Future<?> eventListenerJob;
|
||||
protected @Nullable ScheduledFuture<?> pollingJob;
|
||||
protected @Nullable ExecutorService executor;
|
||||
protected @Nullable Future<?> eventListenerJob;
|
||||
|
||||
@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;
|
||||
|
||||
// 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;
|
||||
public String ProtocolAdapterName;
|
||||
public String Vendor;
|
||||
public String UID;
|
||||
public String Type;
|
||||
public JsonArray DeviceClasses;
|
||||
public String Version;
|
||||
public String TimestampAdded;
|
||||
public JsonObject Error;
|
||||
public JsonObject Properties;
|
||||
|
||||
HomeDevice() {
|
||||
}
|
||||
|
||||
public FullyQualifiedApplianceIdentifier getApplianceIdentifier() {
|
||||
return new FullyQualifiedApplianceIdentifier(this.UID);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getSerialNumber() {
|
||||
return Properties.get("serial.number").getAsString();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getFirmwareVersion() {
|
||||
return Properties.get("firmware.version").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();
|
||||
}
|
||||
|
||||
public String getConnectionBaudRate() {
|
||||
JsonElement baudRate = Properties.get("connection.baud.rate");
|
||||
if (baudRate == null) {
|
||||
return null;
|
||||
}
|
||||
return baudRate.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 {
|
||||
public String DeviceClassType;
|
||||
public JsonArray Operations;
|
||||
public String DeviceClass;
|
||||
public JsonArray Properties;
|
||||
|
||||
DeviceClassObject() {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceOperation {
|
||||
public String Name;
|
||||
public String Arguments;
|
||||
public JsonObject Metadata;
|
||||
|
||||
DeviceOperation() {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeviceProperty {
|
||||
public String Name;
|
||||
public String Value;
|
||||
public int Polling;
|
||||
public JsonObject Metadata;
|
||||
|
||||
DeviceProperty() {
|
||||
}
|
||||
}
|
||||
protected @Nullable URL url;
|
||||
|
||||
public MieleBridgeHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
|
@ -245,9 +134,6 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
// for future usage - no headers to be set for now
|
||||
headers = new HashMap<>();
|
||||
|
||||
onUpdate();
|
||||
lastBridgeConnectionState = false;
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
@ -328,10 +214,8 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
cachedHomeDevicesByRemoteUid.put(hd.getRemoteUid(), hd);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
Set<@NonNull Entry<String, HomeDevice>> cachedEntries = cachedHomeDevicesByApplianceId.entrySet();
|
||||
@NonNull
|
||||
Iterator<@NonNull Entry<String, HomeDevice>> iterator = cachedEntries.iterator();
|
||||
Set<Entry<String, HomeDevice>> cachedEntries = cachedHomeDevicesByApplianceId.entrySet();
|
||||
Iterator<Entry<String, HomeDevice>> iterator = cachedEntries.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Entry<String, HomeDevice> cachedEntry = iterator.next();
|
||||
|
@ -349,11 +233,13 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
for (Thing appliance : getThing().getThings()) {
|
||||
if (appliance.getStatus() == ThingStatus.ONLINE) {
|
||||
String applianceId = (String) appliance.getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = getApplianceIdentifierFromApplianceId(
|
||||
applianceId);
|
||||
FullyQualifiedApplianceIdentifier applianceIdentifier = null;
|
||||
if (applianceId != null) {
|
||||
applianceIdentifier = getApplianceIdentifierFromApplianceId(applianceId);
|
||||
}
|
||||
|
||||
if (applianceIdentifier == null) {
|
||||
logger.error("The appliance with ID '{}' was not found in appliance list from bridge.",
|
||||
logger.warn("The appliance with ID '{}' was not found in appliance list from bridge.",
|
||||
applianceId);
|
||||
continue;
|
||||
}
|
||||
|
@ -363,29 +249,33 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
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 (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;
|
||||
}
|
||||
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onApplianceStateChanged(applianceIdentifier, dco);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while querying an appliance : '{}'",
|
||||
e.getMessage());
|
||||
// Skip com.prosyst.mbs.services.zigbee.hdm.deviceclasses.ReportingControl
|
||||
if (dco == null || !dco.DeviceClass.startsWith(MIELE_CLASS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
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());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.debug("An exception occurred while polling an appliance: '{}'", e.getMessage());
|
||||
} else {
|
||||
logger.debug("An exception occurred while polling an appliance: '{}' -> '{}'", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,12 +286,9 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
// That's why we do an HTTP access instead
|
||||
|
||||
// If there is no connection, this line will fail
|
||||
JsonElement result = invokeRPC("system.listMethods", null);
|
||||
if (result == null) {
|
||||
logger.debug("{} is not reachable", ipAddress);
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
invokeRPC("system.listMethods", new Object[0]);
|
||||
} catch (MieleRpcException e) {
|
||||
logger.debug("{} is not reachable", ipAddress);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -421,16 +308,24 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
|
||||
for (JsonElement obj : result.getAsJsonArray()) {
|
||||
HomeDevice hd = gson.fromJson(obj, HomeDevice.class);
|
||||
devices.add(hd);
|
||||
if (hd != null) {
|
||||
devices.add(hd);
|
||||
}
|
||||
}
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.debug("An exception occurred while getting the home devices: '{}'", e.getMessage());
|
||||
} else {
|
||||
logger.debug("An exception occurred while getting the home devices: '{}' -> '{}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while getting the home devices :'{}'", e.getMessage());
|
||||
}
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
private FullyQualifiedApplianceIdentifier getApplianceIdentifierFromApplianceId(String applianceId) {
|
||||
private @Nullable FullyQualifiedApplianceIdentifier getApplianceIdentifierFromApplianceId(String applianceId) {
|
||||
HomeDevice homeDevice = this.cachedHomeDevicesByApplianceId.get(applianceId);
|
||||
if (homeDevice == null) {
|
||||
return null;
|
||||
|
@ -475,19 +370,17 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
logger.debug("Received a multicast event '{}' from '{}:{}'", event, packet.getAddress(),
|
||||
packet.getPort());
|
||||
|
||||
DeviceProperty dp = new DeviceProperty();
|
||||
String id = null;
|
||||
|
||||
String[] parts = event.split("&");
|
||||
String id = null, name = null, value = null;
|
||||
for (String p : parts) {
|
||||
String[] subparts = p.split("=");
|
||||
switch (subparts[0]) {
|
||||
case "property": {
|
||||
dp.Name = subparts[1];
|
||||
name = subparts[1];
|
||||
break;
|
||||
}
|
||||
case "value": {
|
||||
dp.Value = subparts[1].strip().trim();
|
||||
value = subparts[1].strip().trim();
|
||||
break;
|
||||
}
|
||||
case "id": {
|
||||
|
@ -497,7 +390,7 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
}
|
||||
}
|
||||
|
||||
if (id == null) {
|
||||
if (id == null || name == null || value == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -514,8 +407,11 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
}
|
||||
applianceIdentifier = device.getApplianceIdentifier();
|
||||
}
|
||||
var deviceProperty = new DeviceProperty();
|
||||
deviceProperty.Name = name;
|
||||
deviceProperty.Value = value;
|
||||
for (ApplianceStatusListener listener : applianceStatusListeners) {
|
||||
listener.onAppliancePropertyChanged(applianceIdentifier, dp);
|
||||
listener.onAppliancePropertyChanged(applianceIdentifier, deviceProperty);
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
try {
|
||||
|
@ -549,18 +445,15 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
}
|
||||
};
|
||||
|
||||
public JsonElement invokeOperation(String applianceId, String modelID, String methodName) {
|
||||
public JsonElement invokeOperation(String applianceId, String modelID, String methodName) throws MieleRpcException {
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
logger.debug("The Bridge is offline - operations can not be invoked.");
|
||||
return null;
|
||||
throw new MieleRpcException("Bridge is offline, operations can not be invoked");
|
||||
}
|
||||
|
||||
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;
|
||||
throw new MieleRpcException("Appliance with ID" + applianceId
|
||||
+ " was not found in appliance list from gateway - operations can not be invoked");
|
||||
}
|
||||
|
||||
Object[] args = new Object[4];
|
||||
|
@ -572,65 +465,72 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
return invokeRPC("HDAccess/invokeDCOOperation", args);
|
||||
}
|
||||
|
||||
protected JsonElement invokeRPC(String methodName, Object[] args) {
|
||||
int id = rand.nextInt(Integer.MAX_VALUE);
|
||||
protected JsonElement invokeRPC(String methodName, Object[] args) throws MieleRpcException {
|
||||
JsonElement result = null;
|
||||
URL url = this.url;
|
||||
if (url == null) {
|
||||
throw new MieleRpcException("URL is not set");
|
||||
}
|
||||
|
||||
JsonObject req = new JsonObject();
|
||||
int id = rand.nextInt(Integer.MAX_VALUE);
|
||||
req.addProperty("jsonrpc", "2.0");
|
||||
req.addProperty("id", id);
|
||||
req.addProperty("method", methodName);
|
||||
|
||||
JsonElement result = null;
|
||||
|
||||
JsonArray params = new JsonArray();
|
||||
if (args != null) {
|
||||
for (Object o : args) {
|
||||
params.add(gson.toJsonTree(o));
|
||||
}
|
||||
for (Object o : args) {
|
||||
params.add(gson.toJsonTree(o));
|
||||
}
|
||||
req.add("params", params);
|
||||
|
||||
String requestData = req.toString();
|
||||
String responseData = null;
|
||||
try {
|
||||
responseData = post(url, headers, requestData);
|
||||
} catch (Exception e) {
|
||||
logger.debug("An exception occurred while posting data : '{}'", e.getMessage());
|
||||
responseData = post(url, Collections.emptyMap(), requestData);
|
||||
} catch (IOException e) {
|
||||
throw new MieleRpcException("Exception occurred while posting data", e);
|
||||
}
|
||||
|
||||
if (responseData != null) {
|
||||
logger.trace("The request '{}' yields '{}'", requestData, responseData);
|
||||
JsonObject resp = (JsonObject) JsonParser.parseReader(new StringReader(responseData));
|
||||
logger.trace("The request '{}' yields '{}'", requestData, responseData);
|
||||
JsonObject parsedResponse = null;
|
||||
try {
|
||||
parsedResponse = (JsonObject) JsonParser.parseReader(new StringReader(responseData));
|
||||
} catch (JsonParseException e) {
|
||||
throw new MieleRpcException("Error parsing JSON response", e);
|
||||
}
|
||||
|
||||
result = resp.get("result");
|
||||
JsonElement error = resp.get("error");
|
||||
|
||||
if (error != null && !error.isJsonNull()) {
|
||||
if (error.isJsonPrimitive()) {
|
||||
logger.debug("A remote exception occurred: '{}'", error.getAsString());
|
||||
} else if (error.isJsonObject()) {
|
||||
JsonObject o = error.getAsJsonObject();
|
||||
Integer code = (o.has("code") ? o.get("code").getAsInt() : null);
|
||||
String message = (o.has("message") ? o.get("message").getAsString() : null);
|
||||
String data = (o.has("data") ? (o.get("data") instanceof JsonObject ? o.get("data").toString()
|
||||
: o.get("data").getAsString()) : null);
|
||||
logger.debug("A remote exception occurred: '{}':'{}':'{}'", code, message, data);
|
||||
} else {
|
||||
logger.debug("An unknown remote exception occurred: '{}'", error.toString());
|
||||
}
|
||||
JsonElement error = parsedResponse.get("error");
|
||||
if (error != null && !error.isJsonNull()) {
|
||||
if (error.isJsonPrimitive()) {
|
||||
throw new MieleRpcException("Remote exception occurred: '" + error.getAsString() + "'");
|
||||
} else if (error.isJsonObject()) {
|
||||
JsonObject o = error.getAsJsonObject();
|
||||
Integer code = (o.has("code") ? o.get("code").getAsInt() : null);
|
||||
String message = (o.has("message") ? o.get("message").getAsString() : null);
|
||||
String data = (o.has("data")
|
||||
? (o.get("data") instanceof JsonObject ? o.get("data").toString() : o.get("data").getAsString())
|
||||
: null);
|
||||
throw new MieleRpcException(
|
||||
"Remote exception occurred: '" + code + "':'" + message + "':'" + data + "'");
|
||||
} else {
|
||||
throw new MieleRpcException("Unknown remote exception occurred: '" + error.toString() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
result = parsedResponse.get("result");
|
||||
if (result == null) {
|
||||
throw new MieleRpcException("Result is missing in response");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String post(URL url, Map<String, String> headers, String data) throws IOException {
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
if (headers != null) {
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
connection.addRequestProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||
connection.addRequestProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
connection.addRequestProperty("Accept-Encoding", "gzip");
|
||||
|
@ -688,16 +588,21 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
|
||||
private synchronized void onUpdate() {
|
||||
logger.debug("Scheduling the Miele polling job");
|
||||
ScheduledFuture<?> pollingJob = this.pollingJob;
|
||||
if (pollingJob == null || pollingJob.isCancelled()) {
|
||||
logger.trace("Scheduling the Miele polling job period is {}", POLLING_PERIOD);
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, POLLING_PERIOD, TimeUnit.SECONDS);
|
||||
this.pollingJob = pollingJob;
|
||||
logger.trace("Scheduling the Miele polling job Job is done ?{}", pollingJob.isDone());
|
||||
}
|
||||
logger.debug("Scheduling the Miele event listener job");
|
||||
|
||||
Future<?> eventListenerJob = this.eventListenerJob;
|
||||
if (eventListenerJob == null || eventListenerJob.isCancelled()) {
|
||||
executor = Executors.newSingleThreadExecutor(new NamedThreadFactory("binding-miele"));
|
||||
eventListenerJob = executor.submit(eventListenerRunnable);
|
||||
ExecutorService executor = Executors
|
||||
.newSingleThreadExecutor(new NamedThreadFactory("binding-" + BINDING_ID));
|
||||
this.executor = executor;
|
||||
this.eventListenerJob = executor.submit(eventListenerRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,9 +630,6 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
}
|
||||
|
||||
public boolean registerApplianceStatusListener(ApplianceStatusListener applianceStatusListener) {
|
||||
if (applianceStatusListener == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a null ApplianceStatusListener.");
|
||||
}
|
||||
boolean result = applianceStatusListeners.add(applianceStatusListener);
|
||||
if (result && isInitialized()) {
|
||||
onUpdate();
|
||||
|
@ -759,17 +661,20 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
|
|||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
ScheduledFuture<?> pollingJob = this.pollingJob;
|
||||
if (pollingJob != null) {
|
||||
pollingJob.cancel(true);
|
||||
pollingJob = null;
|
||||
this.pollingJob = null;
|
||||
}
|
||||
Future<?> eventListenerJob = this.eventListenerJob;
|
||||
if (eventListenerJob != null) {
|
||||
eventListenerJob.cancel(true);
|
||||
eventListenerJob = null;
|
||||
this.eventListenerJob = null;
|
||||
}
|
||||
ExecutorService executor = this.executor;
|
||||
if (executor != null) {
|
||||
executor.shutdownNow();
|
||||
executor = null;
|
||||
this.executor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,11 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -43,39 +45,35 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Kai Kreuzer - Changed START_TIME to DateTimeType
|
||||
* @author Jacob Laursen - Added UoM for temperatures, raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum OvenChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false),
|
||||
PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM("", PROGRAM_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAMTYPE("programType", "type", StringType.class, false),
|
||||
PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PHASES, MISSING_PHASE_TEXT_PREFIX,
|
||||
MIELE_OVEN_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -89,7 +87,8 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DURATION("duration", "duration", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -103,7 +102,8 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -117,7 +117,8 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -131,32 +132,37 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
TARGET_TEMP("targetTemperature", "target", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
MEASURED_TEMP("measuredTemperature", "measured", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
DEVICE_TEMP_ONE("deviceTemperature1", "temp1", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
DEVICE_TEMP_TWO("deviceTemperature2", "temp2", QuantityType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false) {
|
||||
@Override
|
||||
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -168,12 +174,12 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
STOP(null, "stop", OnOffType.class, false),
|
||||
SWITCH(null, "switch", OnOffType.class, false);
|
||||
STOP("", "stop", OnOffType.class, false),
|
||||
SWITCH("", "switch", OnOffType.class, false);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(OvenChannelSelector.class);
|
||||
|
||||
private static final 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"));
|
||||
|
||||
|
@ -215,12 +221,13 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -247,7 +254,7 @@ public enum OvenChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
public State getTemperatureState(String s) {
|
||||
|
|
|
@ -15,6 +15,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.MIELE_DEVICE_CLASS_OVEN;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -36,6 +38,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(OvenHandler.class);
|
||||
|
@ -50,32 +53,39 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
OvenChannelSelector selector = (OvenChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOn");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOff");
|
||||
}
|
||||
break;
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOn");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "switchOff");
|
||||
}
|
||||
case STOP: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case STOP: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +97,14 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,11 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -42,49 +44,42 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Kai Kreuzer - Changed START_TIME to DateTimeType
|
||||
* @author Jacob Laursen - Added raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, programs, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PROGRAMS, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
MIELE_TUMBLE_DRYER_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAM("", PROGRAM_CHANNEL_ID, DecimalType.class, false),
|
||||
PROGRAMTYPE("programType", "type", StringType.class, false),
|
||||
PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PHASES, MISSING_PHASE_TEXT_PREFIX,
|
||||
MIELE_TUMBLE_DRYER_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -98,7 +93,8 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DURATION("duration", "duration", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -112,7 +108,8 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -126,7 +123,8 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -140,14 +138,16 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DRYING_STEP("dryingStep", "step", DecimalType.class, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getState(s);
|
||||
}
|
||||
},
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false) {
|
||||
@Override
|
||||
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -159,11 +159,11 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
SWITCH(null, "switch", OnOffType.class, false);
|
||||
SWITCH("", "switch", OnOffType.class, false);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TumbleDryerChannelSelector.class);
|
||||
|
||||
private static final Map<String, String> programs = Map.ofEntries(entry("10", "automatic-plus"),
|
||||
private static final Map<String, String> PROGRAMS = Map.ofEntries(entry("10", "automatic-plus"),
|
||||
entry("20", "cottons"), 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-eco"),
|
||||
|
@ -173,7 +173,7 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
entry("190", "standard-pillows"), entry("220", "basket-programme"), entry("240", "smoothing"),
|
||||
entry("65000", "cottons-auto-load-control"), entry("65001", "minimum-iron-auto-load-control"));
|
||||
|
||||
private static final 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-plus"), entry("7", "cooling-down"),
|
||||
entry("8", "drying-hand-iron"), entry("10", "finished"));
|
||||
|
@ -217,12 +217,13 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -249,6 +250,6 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,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.MIELE_DEVICE_CLASS_TUMBLE_DRYER;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -36,6 +38,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
|
||||
**/
|
||||
@NonNullByDefault
|
||||
public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannelSelector> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TumbleDryerHandler.class);
|
||||
|
@ -50,26 +53,33 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
TumbleDryerChannelSelector selector = (TumbleDryerChannelSelector) getValueSelectorFromChannelID(channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +91,14 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,11 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.openhab.binding.miele.internal.DeviceMetaData;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.miele.internal.DeviceUtil;
|
||||
import org.openhab.binding.miele.internal.MieleTranslationProvider;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -43,49 +45,42 @@ import org.slf4j.LoggerFactory;
|
|||
* @author Kai Kreuzer - Changed START_TIME to DateTimeType
|
||||
* @author Jacob Laursen - Added power/water consumption channels, UoM for temperatures, raw channels
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
||||
|
||||
PRODUCT_TYPE("productTypeId", "productType", StringType.class, true, false),
|
||||
DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true, false),
|
||||
STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getStateTextState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
STATE(null, STATE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
STATE("", STATE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, programs, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PROGRAMS, MISSING_PROGRAM_TEXT_PREFIX,
|
||||
MIELE_WASHING_MACHINE_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAM("", PROGRAM_CHANNEL_ID, DecimalType.class, false, false),
|
||||
PROGRAMTYPE("programType", "type", StringType.class, false, false),
|
||||
PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX,
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return DeviceUtil.getTextState(s, dmd, translationProvider, PHASES, MISSING_PHASE_TEXT_PREFIX,
|
||||
MIELE_WASHING_MACHINE_TEXT_PREFIX);
|
||||
if (state != null) {
|
||||
return state;
|
||||
}
|
||||
return super.getState(s, dmd, translationProvider);
|
||||
}
|
||||
},
|
||||
PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false, false),
|
||||
START_TIME("startTime", "start", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -99,7 +94,8 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DURATION("duration", "duration", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -113,7 +109,8 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -127,7 +124,8 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
FINISH_TIME("finishTime", "finish", DateTimeType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
|
||||
|
@ -141,13 +139,15 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
TARGET_TEMP("targetTemperature", "target", QuantityType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return getTemperatureState(s);
|
||||
}
|
||||
},
|
||||
SPINNING_SPEED("spinningSpeed", "spinningspeed", StringType.class, false, false) {
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("0".equals(s)) {
|
||||
return getState("Without spinning");
|
||||
}
|
||||
|
@ -159,8 +159,8 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
},
|
||||
DOOR("signalDoor", "door", OpenClosedType.class, false, false) {
|
||||
@Override
|
||||
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
if ("true".equals(s)) {
|
||||
return getState("OPEN");
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
return UnDefType.UNDEF;
|
||||
}
|
||||
},
|
||||
SWITCH(null, "switch", OnOffType.class, false, false),
|
||||
SWITCH("", "switch", OnOffType.class, false, false),
|
||||
POWER_CONSUMPTION(EXTENDED_DEVICE_STATE_PROPERTY_NAME, POWER_CONSUMPTION_CHANNEL_ID, QuantityType.class, false,
|
||||
true),
|
||||
WATER_CONSUMPTION(EXTENDED_DEVICE_STATE_PROPERTY_NAME, WATER_CONSUMPTION_CHANNEL_ID, QuantityType.class, false,
|
||||
|
@ -180,7 +180,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(WashingMachineChannelSelector.class);
|
||||
|
||||
private static final 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"),
|
||||
|
@ -189,7 +189,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 static final 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"));
|
||||
|
||||
|
@ -234,12 +234,13 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd,
|
||||
@Nullable MieleTranslationProvider translationProvider) {
|
||||
return this.getState(s, dmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState(String s, DeviceMetaData dmd) {
|
||||
public State getState(String s, @Nullable DeviceMetaData dmd) {
|
||||
if (dmd != null) {
|
||||
String localizedValue = dmd.getMieleEnum(s);
|
||||
if (localizedValue == null) {
|
||||
|
@ -266,7 +267,7 @@ public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
|
|||
logger.error("An exception occurred while converting '{}' into a State", s);
|
||||
}
|
||||
|
||||
return null;
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
public State getTemperatureState(String s) {
|
||||
|
|
|
@ -19,6 +19,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.WATER_CON
|
|||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
@ -42,6 +44,7 @@ import com.google.gson.JsonElement;
|
|||
* @author Martin Lepsy - fixed handling of empty JSON results
|
||||
* @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN), added power/water consumption channels
|
||||
**/
|
||||
@NonNullByDefault
|
||||
public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineChannelSelector>
|
||||
implements ExtendedDeviceStateListener {
|
||||
|
||||
|
@ -62,27 +65,34 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
|||
|
||||
String channelID = channelUID.getId();
|
||||
String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
|
||||
if (applianceId == null) {
|
||||
logger.warn("Command '{}' failed, appliance id is unknown", command);
|
||||
return;
|
||||
}
|
||||
|
||||
WashingMachineChannelSelector selector = (WashingMachineChannelSelector) getValueSelectorFromChannelID(
|
||||
channelID);
|
||||
JsonElement result = null;
|
||||
|
||||
try {
|
||||
if (selector != null) {
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
switch (selector) {
|
||||
case SWITCH: {
|
||||
MieleBridgeHandler bridgeHandler = this.bridgeHandler;
|
||||
if (bridgeHandler == null) {
|
||||
logger.warn("Command '{}' failed, missing bridge handler", command);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
|
||||
} else if (command.equals(OnOffType.OFF)) {
|
||||
result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(command instanceof RefreshType)) {
|
||||
logger.debug("{} is a read-only channel that does not accept commands",
|
||||
selector.getChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +104,14 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
|
|||
logger.warn(
|
||||
"An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
|
||||
channelID, command.toString());
|
||||
} catch (MieleRpcException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause == null) {
|
||||
logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
|
||||
} else {
|
||||
logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
|
||||
cause.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,15 @@
|
|||
package org.openhab.binding.miele.internal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.openhab.binding.miele.internal.api.dto.DeviceMetaData;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.test.java.JavaTest;
|
||||
|
@ -28,9 +33,12 @@ import org.openhab.core.types.UnDefType;
|
|||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class DeviceUtilTest extends JavaTest {
|
||||
|
||||
private @NonNullByDefault({}) @Mock MieleTranslationProvider translationProvider;
|
||||
|
||||
@Test
|
||||
public void bytesToHexWhenTopBitIsUsedReturnsCorrectString() {
|
||||
String actual = DeviceUtil.bytesToHex(new byte[] { (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef });
|
||||
|
@ -70,11 +78,6 @@ public class DeviceUtilTest extends JavaTest {
|
|||
assertThrows(NumberFormatException.class, () -> DeviceUtil.getTemperatureState("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemperatureStateNullValueThrowsNumberFormatException() {
|
||||
assertThrows(NumberFormatException.class, () -> DeviceUtil.getTemperatureState(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getStateTextStateProviderHasPrecedence() {
|
||||
assertEquals("I brug", this.getStateTextState("5", "Running", "miele.state.running", "I brug"));
|
||||
|
@ -82,19 +85,22 @@ public class DeviceUtilTest extends JavaTest {
|
|||
|
||||
@Test
|
||||
public void getStateTextStateGatewayTextIsReturnedWhenKeyIsUnknown() {
|
||||
assertEquals("Running", this.getStateTextState("-1", "Running", "key.unknown", "I brug"));
|
||||
assertEquals("Running", this.getStateTextState("-1", "Running"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getStateTextStateKeyIsReturnedWhenUnknownByGatewayAndProvider() {
|
||||
assertEquals("state.99", this.getStateTextState("99", null, "key.unknown", "I brug"));
|
||||
assertEquals("state.99", this.getStateTextState("99", null));
|
||||
}
|
||||
|
||||
private String getStateTextState(String value, String localizedValue, String mockedKey, String mockedValue) {
|
||||
when(translationProvider.getText(mockedKey, localizedValue)).thenReturn(mockedValue);
|
||||
return getStateTextState(value, localizedValue);
|
||||
}
|
||||
|
||||
private String getStateTextState(String value, @Nullable String localizedValue) {
|
||||
var metaData = new DeviceMetaData();
|
||||
metaData.LocalizedValue = localizedValue;
|
||||
var translationProvider = mock(MieleTranslationProvider.class);
|
||||
when(translationProvider.getText(mockedKey, metaData.LocalizedValue)).thenReturn(mockedValue);
|
||||
|
||||
return DeviceUtil.getStateTextState(value, metaData, translationProvider).toString();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.openhab.binding.miele.internal;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.core.test.java.JavaTest;
|
||||
|
||||
|
@ -23,6 +24,7 @@ import org.openhab.core.test.java.JavaTest;
|
|||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FullyQualifiedApplianceIdentifierTest extends JavaTest {
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue