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