]> git.basschouten.com Git - openhab-addons.git/commitdiff
[miele] Fix multicast and multi-protocol support (ZigBee/Wi-Fi) (#11244)
authorjlaur <jacob-github@vindvejr.dk>
Sat, 18 Sep 2021 20:59:18 +0000 (22:59 +0200)
committerGitHub <noreply@github.com>
Sat, 18 Sep 2021 20:59:18 +0000 (22:59 +0200)
* Fix multicast and multi-protocol support (ZigBee/Wi-Fi)
* Fix channel description referring to hood but also used for oven and other appliances.
* Fix auto-discovery finding already configured things through files.

Fixes #11242

Fixes #11243

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
27 files changed:
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/FullyQualifiedApplianceIdentifier.java [new file with mode: 0644]
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleApplianceDiscoveryService.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleMDNSDiscoveryParticipant.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceStatusListener.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishWasherHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleBridgeHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java
bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/channeltypes.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/coffeemachine.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/dishwasher.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/fridge.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/fridgefreezer.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/hob.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/hood.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/oven.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/tumbledryer.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/washingmachine.xml
bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/xgw3000.xml
bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/FullyQualifiedApplianceIdentifierTest.java [new file with mode: 0644]

diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/FullyQualifiedApplianceIdentifier.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/FullyQualifiedApplianceIdentifier.java
new file mode 100644 (file)
index 0000000..2ecfd85
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2010-2021 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;
+
+/**
+ * The {@link FullyQualifiedApplianceIdentifier} class represents a fully qualified appliance identifier.
+ * Example: "hdm:ZigBee:0123456789abcdef#210"
+ *
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
+ */
+public class FullyQualifiedApplianceIdentifier {
+    private String uid;
+    private String protocol;
+    private String applianceId;
+
+    public FullyQualifiedApplianceIdentifier(String uid) {
+        this.uid = uid;
+
+        int separatorPosition = this.uid.lastIndexOf(':') + 1;
+        this.protocol = uid.substring(0, separatorPosition);
+        this.applianceId = uid.substring(separatorPosition);
+    }
+
+    public FullyQualifiedApplianceIdentifier(String applianceId, String protocol) {
+        this.uid = protocol + applianceId;
+        this.protocol = protocol;
+        this.applianceId = applianceId;
+    }
+
+    /**
+     * @return UID of appliance (e.g. "hdm:ZigBee:0123456789abcdef#210")
+     */
+    public String getUid() {
+        return this.uid;
+    }
+
+    /**
+     * @return Appliance ID without protocol adapter information (e.g. "0123456789abcdef#210")
+     */
+    public String getApplianceId() {
+        return this.applianceId;
+    }
+
+    public String getId() {
+        return this.getApplianceId().replaceAll("[^a-zA-Z0-9_]", "_");
+    }
+
+    /**
+     * @return Protocol prefix of fully qualified appliance identifier (e.g. "hdmi:ZigBee:"")
+     */
+    public String getProtocol() {
+        return this.protocol;
+    }
+}
index 5cf2da31a74644de6aa3f86ad46e63ad9bf601fe..b435fc7c723df7b2e46498051b06287820810ac7 100644 (file)
@@ -21,6 +21,7 @@ import org.openhab.core.thing.ThingTypeUID;
  *
  * @author Karel Goderis - Initial contribution
  * @author Martin Lepsy - added constants for support of WiFi devices & protocol
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 @NonNullByDefault
 public class MieleBindingConstants {
@@ -28,9 +29,8 @@ public class MieleBindingConstants {
     public static final String BINDING_ID = "miele";
     public static final String APPLIANCE_ID = "uid";
     public static final String DEVICE_CLASS = "dc";
-    public static final String HDM_LAN = "hdm:LAN:";
-    public static final String HDM_ZIGBEE = "hdm:ZigBee:";
     public static final String PROTOCOL_PROPERTY_NAME = "protocol";
+    public static final String SERIAL_NUMBER_PROPERTY_NAME = "serialNumber";
 
     // List of all Thing Type UIDs
     public static final ThingTypeUID THING_TYPE_XGW3000 = new ThingTypeUID(BINDING_ID, "xgw3000");
index b85ce8e11763d74e79475f52134b168b04fd847d..703c5549b54393e414ea7a7d1788005f6e80c757 100644 (file)
@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.binding.miele.internal.handler.ApplianceStatusListener;
 import org.openhab.binding.miele.internal.handler.MieleApplianceHandler;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler;
@@ -42,6 +43,7 @@ import com.google.gson.JsonElement;
  *
  * @author Karel Goderis - Initial contribution
  * @author Martin Lepsy - Added protocol information in order so support WiFi devices
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements ApplianceStatusListener {
 
@@ -101,8 +103,10 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
             ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
             Map<String, Object> properties = new HashMap<>(2);
 
-            properties.put(PROTOCOL_PROPERTY_NAME, appliance.getProtocol());
-            properties.put(APPLIANCE_ID, appliance.getApplianceId());
+            FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
+            properties.put(PROTOCOL_PROPERTY_NAME, applianceIdentifier.getProtocol());
+            properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId());
+            properties.put(SERIAL_NUMBER_PROPERTY_NAME, appliance.getSerialNumber());
 
             for (JsonElement dc : appliance.DeviceClasses) {
                 String dcStr = dc.getAsString();
@@ -113,7 +117,8 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
             }
 
             DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
-                    .withBridge(bridgeUID).withLabel((String) properties.get(DEVICE_CLASS)).build();
+                    .withBridge(bridgeUID).withLabel((String) properties.get(DEVICE_CLASS))
+                    .withRepresentationProperty(APPLIANCE_ID).build();
 
             thingDiscovered(discoveryResult);
         } else {
@@ -132,12 +137,17 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
     }
 
     @Override
-    public void onApplianceStateChanged(String uid, DeviceClassObject dco) {
+    public void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceClassObject dco) {
         // nothing to do
     }
 
     @Override
-    public void onAppliancePropertyChanged(String uid, DeviceProperty dp) {
+    public void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceProperty dp) {
+        // nothing to do
+    }
+
+    @Override
+    public void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp) {
         // nothing to do
     }
 
@@ -158,7 +168,7 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp
                     modelID.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase());
 
             if (getSupportedThingTypes().contains(thingTypeUID)) {
-                ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, appliance.getId());
+                ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, appliance.getApplianceIdentifier().getId());
                 return thingUID;
             } else {
                 return null;
index 7694c88c233232623d1a21e90df3d0db8f1108ea..eef48f6b0222fa172b1842865e6fb10959e80c36 100644 (file)
@@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author Karel Goderis - Initial contribution
  * @author Martin Lepsy - Added check for Miele gateway for cleaner discovery
- *
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 @Component
 public class MieleMDNSDiscoveryParticipant implements MDNSDiscoveryParticipant {
@@ -83,8 +83,7 @@ public class MieleMDNSDiscoveryParticipant implements MDNSDiscoveryParticipant {
                 }
 
                 return DiscoveryResultBuilder.create(uid).withProperties(properties)
-                        .withRepresentationProperty(MieleBindingConstants.HOST).withLabel("Miele XGW3000 Gateway")
-                        .build();
+                        .withRepresentationProperty(MieleBindingConstants.HOST).withLabel("Miele XGW3000").build();
             }
         }
         return null;
index 153f35956f71a04aab682bc0164fc6dfc51a7e04..769417bf60cd6146e90be1986e444fa7e6a0f58e 100644 (file)
@@ -12,6 +12,7 @@
  */
 package org.openhab.binding.miele.internal.handler;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
@@ -22,24 +23,33 @@ import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
  * an appliance has been removed or added.
  *
  * @author Karel Goderis - Initial contribution
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public interface ApplianceStatusListener {
 
     /**
      * This method is called whenever the state of the given appliance has changed.
      *
-     * @param uid the UID of the aplliance that has changed
+     * @param applianceIdentifier the fully qualified identifier of the appliance that has changed
      * @param dco the POJO containing the new state (properties and/or operations)
      */
-    void onApplianceStateChanged(String uid, DeviceClassObject dco);
+    void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceClassObject dco);
 
     /**
      * This method is called whenever a "property" of the given appliance has changed.
      *
-     * @param uid the UID of the aplliance that has changed
+     * @param applianceIdentifier the fully qualified identifier of the appliance that has changed
      * @param dco the POJO containing the new state of the property
      */
-    void onAppliancePropertyChanged(String uid, DeviceProperty dp);
+    void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceProperty dp);
+
+    /**
+     * This method is called whenever a "property" of the given appliance has changed.
+     *
+     * @param serialNumber The serial number of the appliance that has changed
+     * @param dco the POJO containing the new state of the property
+     */
+    void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp);
 
     /**
      * This method us called whenever an appliance is removed.
index 5b7ed1dd37591f4cacf2ebe7a0d3e079f8d3a16f..0b0cbc34c3b069c98f11c1f8e5bf53b065108108 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -30,6 +32,7 @@ import com.google.gson.JsonElement;
  *
  * @author Stephan Esch - Initial contribution
  * @author Martin Lepsy - fixed handling of empty JSON results
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineChannelSelector> {
 
@@ -44,7 +47,9 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         CoffeeMachineChannelSelector selector = (CoffeeMachineChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -54,9 +59,9 @@ public class CoffeeMachineHandler extends MieleApplianceHandler<CoffeeMachineCha
                 switch (selector) {
                     case SWITCH: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "switchOn");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOn");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "switchOff");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOff");
                         }
                         break;
                     }
index 570544aa62bcedca98985d57d9b94f892f80db70..dc06b24575fb8317f1b35cecf57cde4b8aa55f76 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -31,6 +33,7 @@ import com.google.gson.JsonElement;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - fixed handling of REFRESH commands
  * @author Martin Lepsy - fixed handling of empty JSON results
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSelector> {
 
@@ -45,7 +48,9 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         DishwasherChannelSelector selector = (DishwasherChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -55,9 +60,9 @@ public class DishWasherHandler extends MieleApplianceHandler<DishwasherChannelSe
                 switch (selector) {
                     case SWITCH: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "start");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stop");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
                         }
                         break;
                     }
index 7dd3716eac7e441d32f2d18ebac725cc011187e8..24dd6f75980b3493340a1727a554822d8c5510d8 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -30,6 +32,7 @@ import com.google.gson.JsonElement;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - fixed handling of REFRESH commands
  * @author Martin Lepsy - fixed handling of empty JSON results
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerChannelSelector> {
 
@@ -44,7 +47,9 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         FridgeFreezerChannelSelector selector = (FridgeFreezerChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -54,17 +59,17 @@ public class FridgeFreezerHandler extends MieleApplianceHandler<FridgeFreezerCha
                 switch (selector) {
                     case SUPERCOOL: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "startSuperCooling");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startSuperCooling");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stopSuperCooling");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopSuperCooling");
                         }
                         break;
                     }
                     case SUPERFREEZE: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "startSuperFreezing");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startSuperFreezing");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stopSuperFreezing");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopSuperFreezing");
                         }
                         break;
                     }
index 2c91956a703878e606c2ae297b65180358ef9637..60db1c257e1283037bfe551c9a363b69f279913c 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -30,6 +32,7 @@ import com.google.gson.JsonElement;
  *
  * @author Karel Goderis - Initial contribution
  * @author Martin Lepsy - fixed handling of empty JSON results
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector> {
 
@@ -44,7 +47,9 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         FridgeChannelSelector selector = (FridgeChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -54,15 +59,15 @@ public class FridgeHandler extends MieleApplianceHandler<FridgeChannelSelector>
                 switch (selector) {
                     case SUPERCOOL: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "startSuperCooling");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startSuperCooling");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stopSuperCooling");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopSuperCooling");
                         }
                         break;
                     }
                     case START: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "start");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
                         }
                         break;
                     }
index cd2dd89b1d42002e6c95c63cf41ad4345f93a3ea..f89c11d0db57728ce906a3086f95a2db637e447f 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -30,7 +32,8 @@ import com.google.gson.JsonElement;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - fixed handling of REFRESH commands
  * @author Martin Lepsy - fixed handling of empty JSON results
- */
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
+ **/
 public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
 
     private final Logger logger = LoggerFactory.getLogger(HoodHandler.class);
@@ -44,7 +47,9 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         HoodChannelSelector selector = (HoodChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -54,15 +59,15 @@ public class HoodHandler extends MieleApplianceHandler<HoodChannelSelector> {
                 switch (selector) {
                     case LIGHT: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "startLighting");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "startLighting");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stopLighting");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stopLighting");
                         }
                         break;
                     }
                     case STOP: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stop");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
                         }
                         break;
                     }
index d6c000340b79ea8ac68c7c6d29589f58dbe7f35b..a4f2b9c1f1abe7a99342e4981df1cc7011e8938d 100644 (file)
@@ -21,6 +21,7 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.apache.commons.lang3.StringUtils;
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
@@ -52,6 +53,7 @@ import com.google.gson.JsonParser;
  *
  * @author Karel Goderis - Initial contribution
  * @author Martin Lepsy - Added check for JsonNull result
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannelSelector> extends BaseThingHandler
         implements ApplianceStatusListener {
@@ -65,7 +67,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
 
     protected Gson gson = new Gson();
 
-    protected String uid;
+    protected String applianceId;
     protected MieleBridgeHandler bridgeHandler;
     private Class<E> selectorType;
     protected String modelID;
@@ -103,9 +105,9 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
     @Override
     public void initialize() {
         logger.debug("Initializing Miele appliance handler.");
-        final String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
-        if (uid != null) {
-            this.uid = uid;
+        final String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        if (applianceId != null) {
+            this.applianceId = applianceId;
             if (getMieleBridgeHandler() != null) {
                 ThingStatusInfo statusInfo = getBridge().getStatusInfo();
                 updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription());
@@ -123,12 +125,12 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
     @Override
     public void dispose() {
         logger.debug("Handler disposes. Unregistering listener.");
-        if (uid != null) {
+        if (applianceId != null) {
             MieleBridgeHandler bridgeHandler = getMieleBridgeHandler();
             if (bridgeHandler != null) {
                 getMieleBridgeHandler().unregisterApplianceStatusListener(this);
             }
-            uid = null;
+            applianceId = null;
         }
     }
 
@@ -142,12 +144,13 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
     }
 
     @Override
-    public void onApplianceStateChanged(String UID, DeviceClassObject dco) {
-        String myUID = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+    public void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applicationIdentifier,
+            DeviceClassObject dco) {
+        String myApplianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
         String modelID = StringUtils.right(dco.DeviceClass,
                 dco.DeviceClass.length() - new String("com.miele.xgw3000.gateway.hdm.deviceclasses.Miele").length());
 
-        if (myUID.equals(UID)) {
+        if (myApplianceId.equals(applicationIdentifier.getApplianceId())) {
             if (modelID.equals(this.modelID)) {
                 for (JsonElement prop : dco.Properties.getAsJsonArray()) {
                     try {
@@ -155,7 +158,7 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
                         dp.Value = StringUtils.trim(dp.Value);
                         dp.Value = StringUtils.strip(dp.Value);
 
-                        onAppliancePropertyChanged(UID, dp);
+                        onAppliancePropertyChanged(applicationIdentifier, dp);
                     } catch (Exception p) {
                         // Ignore - this is due to an unrecognized and not yet reverse-engineered array property
                     }
@@ -165,85 +168,107 @@ public abstract class MieleApplianceHandler<E extends Enum<E> & ApplianceChannel
     }
 
     @Override
-    public void onAppliancePropertyChanged(String UID, DeviceProperty dp) {
-        String myUID = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+    public void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp) {
+        String mySerialNumber = getThing().getProperties().get(SERIAL_NUMBER_PROPERTY_NAME);
+        if (!mySerialNumber.equals(serialNumber)) {
+            return;
+        }
 
-        if (myUID.equals(UID)) {
-            try {
-                DeviceMetaData dmd = null;
-                if (dp.Metadata == null) {
-                    String metadata = metaDataCache.get(new StringBuilder().append(dp.Name).toString().trim());
-                    if (metadata != null) {
-                        JsonObject jsonMetaData = (JsonObject) JsonParser.parseString(metadata);
-                        dmd = gson.fromJson(jsonMetaData, DeviceMetaData.class);
-                        // only keep the enum, if any - that's all we care for events we receive via multicast
-                        // all other fields are nulled
-                        dmd.LocalizedID = null;
-                        dmd.LocalizedValue = null;
-                        dmd.Filter = null;
-                        dmd.description = null;
-                    }
-                }
-                if (dp.Metadata != null) {
-                    String metadata = StringUtils.replace(dp.Metadata.toString(), "enum", "MieleEnum");
+        this.onAppliancePropertyChanged(dp);
+    }
+
+    @Override
+    public void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applicationIdentifier, DeviceProperty dp) {
+        String myApplianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+
+        if (!myApplianceId.equals(applicationIdentifier.getApplianceId())) {
+            return;
+        }
+
+        this.onAppliancePropertyChanged(dp);
+    }
+
+    private void onAppliancePropertyChanged(DeviceProperty dp) {
+        try {
+            DeviceMetaData dmd = null;
+            if (dp.Metadata == null) {
+                String metadata = metaDataCache.get(new StringBuilder().append(dp.Name).toString().trim());
+                if (metadata != null) {
                     JsonObject jsonMetaData = (JsonObject) JsonParser.parseString(metadata);
                     dmd = gson.fromJson(jsonMetaData, DeviceMetaData.class);
-                    metaDataCache.put(new StringBuilder().append(dp.Name).toString().trim(), metadata);
+                    // only keep the enum, if any - that's all we care for events we receive via multicast
+                    // all other fields are nulled
+                    dmd.LocalizedID = null;
+                    dmd.LocalizedValue = null;
+                    dmd.Filter = null;
+                    dmd.description = null;
                 }
+            }
+            if (dp.Metadata != null) {
+                String metadata = StringUtils.replace(dp.Metadata.toString(), "enum", "MieleEnum");
+                JsonObject jsonMetaData = (JsonObject) JsonParser.parseString(metadata);
+                dmd = gson.fromJson(jsonMetaData, DeviceMetaData.class);
+                metaDataCache.put(new StringBuilder().append(dp.Name).toString().trim(), metadata);
+            }
 
-                ApplianceChannelSelector selector = null;
-                try {
-                    selector = getValueSelectorFromMieleID(dp.Name);
-                } catch (Exception h) {
-                    logger.trace("{} is not a valid channel for a {}", dp.Name, modelID);
-                }
+            ApplianceChannelSelector selector = null;
+            try {
+                selector = getValueSelectorFromMieleID(dp.Name);
+            } catch (Exception h) {
+                logger.trace("{} is not a valid channel for a {}", dp.Name, modelID);
+            }
 
-                String dpValue = StringUtils.trim(StringUtils.strip(dp.Value));
-
-                if (selector != null) {
-                    if (!selector.isProperty()) {
-                        ChannelUID theChannelUID = new ChannelUID(getThing().getUID(), selector.getChannelID());
-
-                        if (dp.Value != null) {
-                            logger.trace("Update state of {} with getState '{}'", theChannelUID,
-                                    selector.getState(dpValue, dmd));
-                            updateState(theChannelUID, selector.getState(dpValue, dmd));
-                        } else {
-                            updateState(theChannelUID, UnDefType.UNDEF);
-                        }
-                    } else if (dpValue != null) {
-                        logger.debug("Updating the property '{}' of '{}' to '{}'", selector.getChannelID(),
-                                getThing().getUID(), selector.getState(dpValue, dmd).toString());
-                        Map<String, String> properties = editProperties();
-                        properties.put(selector.getChannelID(), selector.getState(dpValue, dmd).toString());
-                        updateProperties(properties);
+            String dpValue = StringUtils.trim(StringUtils.strip(dp.Value));
+
+            if (selector != null) {
+                if (!selector.isProperty()) {
+                    ChannelUID theChannelUID = new ChannelUID(getThing().getUID(), selector.getChannelID());
+
+                    if (dp.Value != null) {
+                        logger.trace("Update state of {} with getState '{}'", theChannelUID,
+                                selector.getState(dpValue, dmd));
+                        updateState(theChannelUID, selector.getState(dpValue, dmd));
+                    } else {
+                        updateState(theChannelUID, UnDefType.UNDEF);
                     }
+                } else if (dpValue != null) {
+                    logger.debug("Updating the property '{}' of '{}' to '{}'", selector.getChannelID(),
+                            getThing().getUID(), selector.getState(dpValue, dmd).toString());
+                    Map<String, String> properties = editProperties();
+                    properties.put(selector.getChannelID(), selector.getState(dpValue, dmd).toString());
+                    updateProperties(properties);
                 }
-            } catch (IllegalArgumentException e) {
-                logger.error("An exception occurred while processing a changed device property :'{}'", e.getMessage());
             }
+        } catch (IllegalArgumentException e) {
+            logger.error("An exception occurred while processing a changed device property :'{}'", e.getMessage());
         }
     }
 
     @Override
     public void onApplianceRemoved(HomeDevice appliance) {
-        if (uid != null) {
-            if (uid.equals(appliance.getApplianceId())) {
-                updateStatus(ThingStatus.OFFLINE);
-            }
+        if (applianceId == null) {
+            return;
+        }
+
+        if (applianceId.equals(appliance.getApplianceIdentifier().getApplianceId())) {
+            updateStatus(ThingStatus.OFFLINE);
         }
     }
 
     @Override
     public void onApplianceAdded(HomeDevice appliance) {
-        if (uid != null) {
-            if (uid.equals(appliance.getApplianceId())) {
-                Map<String, String> properties = editProperties();
-                properties.put(PROTOCOL_PROPERTY_NAME, appliance.getProtocol());
-                updateProperties(properties);
+        if (applianceId == null) {
+            return;
+        }
 
-                updateStatus(ThingStatus.ONLINE);
-            }
+        FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
+
+        if (applianceId.equals(applianceIdentifier.getApplianceId())) {
+            Map<String, String> properties = editProperties();
+            properties.put(PROTOCOL_PROPERTY_NAME, applianceIdentifier.getProtocol());
+            properties.put(SERIAL_NUMBER_PROPERTY_NAME, appliance.getSerialNumber());
+            updateProperties(properties);
+            updateStatus(ThingStatus.ONLINE);
         }
     }
 
index ad2ac3d7671f057e091f755e3aad2a632aa5bcd1..d40c19cf9c48253d2026f4ccd51eeb34ec89c205 100644 (file)
@@ -45,6 +45,7 @@ import java.util.regex.Pattern;
 import java.util.zip.GZIPInputStream;
 
 import org.apache.commons.lang3.StringUtils;
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.common.NamedThreadFactory;
 import org.openhab.core.thing.Bridge;
 import org.openhab.core.thing.ChannelUID;
@@ -71,7 +72,8 @@ import com.google.gson.JsonParser;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - Fixed lifecycle issues
  * @author Martin Lepsy - Added protocol information to support WiFi devices & some refactoring for HomeDevice
- */
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
+ **/
 public class MieleBridgeHandler extends BaseBridgeHandler {
 
     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_XGW3000);
@@ -103,8 +105,6 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
     // Data structures to de-JSONify whatever Miele appliances are sending us
     public class HomeDevice {
 
-        private static final String PROTOCOL_LAN = "LAN";
-
         public String Name;
         public String Status;
         public String ParentUID;
@@ -121,17 +121,12 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
         HomeDevice() {
         }
 
-        public String getId() {
-            return getApplianceId().replaceAll("[^a-zA-Z0-9_]", "_");
-        }
-
-        public String getProtocol() {
-            return ProtocolAdapterName.equals(PROTOCOL_LAN) ? HDM_LAN : HDM_ZIGBEE;
+        public FullyQualifiedApplianceIdentifier getApplianceIdentifier() {
+            return new FullyQualifiedApplianceIdentifier(this.UID);
         }
 
-        public String getApplianceId() {
-            return ProtocolAdapterName.equals(PROTOCOL_LAN) ? StringUtils.right(UID, UID.length() - HDM_LAN.length())
-                    : StringUtils.right(UID, UID.length() - HDM_ZIGBEE.length());
+        public String getSerialNumber() {
+            return Properties.get("serial.number").getAsString();
         }
     }
 
@@ -269,14 +264,11 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
                                     String applianceId = (String) appliance.getConfiguration().getProperties()
                                             .get(APPLIANCE_ID);
                                     String protocol = appliance.getProperties().get(PROTOCOL_PROPERTY_NAME);
-                                    if (protocol == null) {
-                                        logger.error("Protocol property is missing for {}", applianceId);
-                                        continue;
-                                    }
-                                    String UID = protocol + applianceId;
+                                    var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId,
+                                            protocol);
 
                                     Object[] args = new Object[2];
-                                    args[0] = UID;
+                                    args[0] = applianceIdentifier.getUid();
                                     args[1] = true;
                                     JsonElement result = invokeRPC("HDAccess/getDeviceClassObjects", args);
 
@@ -286,7 +278,7 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
                                                 DeviceClassObject dco = gson.fromJson(obj, DeviceClassObject.class);
 
                                                 for (ApplianceStatusListener listener : applianceStatusListeners) {
-                                                    listener.onApplianceStateChanged(applianceId, dco);
+                                                    listener.onApplianceStateChanged(applianceIdentifier, dco);
                                                 }
                                             } catch (Exception e) {
                                                 logger.debug("An exception occurred while quering an appliance : '{}'",
@@ -384,7 +376,7 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
                                         packet.getPort());
 
                                 DeviceProperty dp = new DeviceProperty();
-                                String uid = null;
+                                String id = null;
 
                                 String[] parts = StringUtils.split(event, "&");
                                 for (String p : parts) {
@@ -399,14 +391,27 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
                                             break;
                                         }
                                         case "id": {
-                                            uid = subparts[1];
+                                            id = subparts[1];
                                             break;
                                         }
                                     }
                                 }
 
-                                for (ApplianceStatusListener listener : applianceStatusListeners) {
-                                    listener.onAppliancePropertyChanged(uid, dp);
+                                if (id == null) {
+                                    continue;
+                                }
+
+                                // In XGW 3000 firmware 2.03 this was changed from UID (hdm:ZigBee:0123456789abcdef#210)
+                                // to serial number (001234567890)
+                                if (id.startsWith("hdm:")) {
+                                    for (ApplianceStatusListener listener : applianceStatusListeners) {
+                                        listener.onAppliancePropertyChanged(new FullyQualifiedApplianceIdentifier(id),
+                                                dp);
+                                    }
+                                } else {
+                                    for (ApplianceStatusListener listener : applianceStatusListeners) {
+                                        listener.onAppliancePropertyChanged(id, dp);
+                                    }
                                 }
                             } catch (SocketTimeoutException e) {
                                 try {
@@ -440,14 +445,11 @@ public class MieleBridgeHandler extends BaseBridgeHandler {
         }
     };
 
-    public JsonElement invokeOperation(String UID, String modelID, String methodName) {
-        return invokeOperation(UID, modelID, methodName, HDM_ZIGBEE);
-    }
-
-    public JsonElement invokeOperation(String UID, String modelID, String methodName, String protocol) {
+    public JsonElement invokeOperation(FullyQualifiedApplianceIdentifier applianceIdentifier, String modelID,
+            String methodName) {
         if (getThing().getStatus() == ThingStatus.ONLINE) {
             Object[] args = new Object[4];
-            args[0] = protocol + UID;
+            args[0] = applianceIdentifier.getUid();
             args[1] = "com.miele.xgw3000.gateway.hdm.deviceclasses.Miele" + modelID;
             args[2] = methodName;
             args[3] = null;
index de84623d18342e8a46cad14775c761bb2240afb5..20d2fdb0ae09ceca553a926d798d4b9b27b04ede 100644 (file)
@@ -15,6 +15,7 @@ package org.openhab.binding.miele.internal.handler;
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
 import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -32,6 +33,7 @@ import com.google.gson.JsonElement;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - fixed handling of REFRESH commands
  * @author Martin Lepsy - fixed handling of empty JSON results
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
  */
 public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
 
@@ -46,8 +48,9 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
-        String protocol = (String) getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         OvenChannelSelector selector = (OvenChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -57,15 +60,15 @@ public class OvenHandler extends MieleApplianceHandler<OvenChannelSelector> {
                 switch (selector) {
                     case SWITCH: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "switchOn", protocol);
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOn");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "switchOff", protocol);
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "switchOff");
                         }
                         break;
                     }
                     case STOP: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stop", protocol);
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
                         }
                         break;
                     }
index 5c1458034eeea7a23b244e44a719d5ff913dfe2c..3ffe5cc12a5133085798112caf497d69597b02cd 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -31,7 +33,8 @@ import com.google.gson.JsonElement;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - fixed handling of REFRESH commands
  * @author Martin Lepsy - fixed handling of empty JSON results
- */
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
+ **/
 public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannelSelector> {
 
     private final Logger logger = LoggerFactory.getLogger(TumbleDryerHandler.class);
@@ -45,7 +48,9 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         TumbleDryerChannelSelector selector = (TumbleDryerChannelSelector) getValueSelectorFromChannelID(channelID);
         JsonElement result = null;
@@ -55,9 +60,9 @@ public class TumbleDryerHandler extends MieleApplianceHandler<TumbleDryerChannel
                 switch (selector) {
                     case SWITCH: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "start");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stop");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
                         }
                         break;
                     }
index 115d5a8a07a64f218a9e3eae03a6a99cce4a9ba6..4abea606bb7faf576d0293b6f19e2803aac5a498 100644 (file)
@@ -13,7 +13,9 @@
 package org.openhab.binding.miele.internal.handler;
 
 import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID;
+import static org.openhab.binding.miele.internal.MieleBindingConstants.PROTOCOL_PROPERTY_NAME;
 
+import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -31,7 +33,8 @@ import com.google.gson.JsonElement;
  * @author Karel Goderis - Initial contribution
  * @author Kai Kreuzer - fixed handling of REFRESH commands
  * @author Martin Lepsy - fixed handling of empty JSON results
- */
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
+ **/
 public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineChannelSelector> {
 
     private final Logger logger = LoggerFactory.getLogger(WashingMachineHandler.class);
@@ -45,7 +48,9 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
         super.handleCommand(channelUID, command);
 
         String channelID = channelUID.getId();
-        String uid = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String applianceId = (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID);
+        String protocol = getThing().getProperties().get(PROTOCOL_PROPERTY_NAME);
+        var applianceIdentifier = new FullyQualifiedApplianceIdentifier(applianceId, protocol);
 
         WashingMachineChannelSelector selector = (WashingMachineChannelSelector) getValueSelectorFromChannelID(
                 channelID);
@@ -56,9 +61,9 @@ public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineC
                 switch (selector) {
                     case SWITCH: {
                         if (command.equals(OnOffType.ON)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "start");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "start");
                         } else if (command.equals(OnOffType.OFF)) {
-                            result = bridgeHandler.invokeOperation(uid, modelID, "stop");
+                            result = bridgeHandler.invokeOperation(applianceIdentifier, modelID, "stop");
                         }
                         break;
                     }
index 6d652dfc2d6682cabdbbaa40c4ce6df30115fe53..f507cfe41c64bc4464b05e59e25a6d8a3714798b 100644 (file)
@@ -76,7 +76,7 @@
        <channel-type id="stop" advanced="false">
                <item-type>Switch</item-type>
                <label>Stop</label>
-               <description>Stop the hood</description>
+               <description>Stop the appliance</description>
        </channel-type>
 
        <channel-type id="step" advanced="true">
index 8a34bfc992d19dc79dd42f4c5409268d80322ffa..09d210dcc90877b64c8b2332e471559cb757ca1a 100644 (file)
@@ -22,6 +22,8 @@
                        <channel id="switch" typeId="switch"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 902fbaced05487dfd648c0baaf97f7d0d867cb6d..e87446bef61e466cc62b66853620a0822835afe3 100644 (file)
@@ -25,6 +25,8 @@
                        <channel id="switch" typeId="switch"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index c68c64337697146da586cde9f68e3053e12b98f5..a50007623b86b4c914c7536b308c12be73f8a32d 100644 (file)
@@ -22,6 +22,8 @@
                        <channel id="start" typeId="switch"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 585ad21d9c4e26f0c61a4049dcb88a40be293fb5..de6aa4371a52515809ebe963f9f5873c0d623a22 100644 (file)
@@ -27,6 +27,8 @@
                        <channel id="start" typeId="switch"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 71e6ab990a5809608481f88aa762080ded1bd4e3..ab12ed6204d07c1c5d3a33dabbc87e3f34ab174c 100644 (file)
@@ -35,6 +35,8 @@
                        <channel id="plate6time" typeId="time"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index aedd3eade74ae1b9f3fb258d0a014adf12776131..af075365e3ca1b66c157534896d1f4ee24924b00 100644 (file)
@@ -20,6 +20,8 @@
                        <channel id="stop" typeId="stop"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 4090178d656acffb1d7009224fc0f7dcae97f76d..ac699106a29fb9d30f7fe24d3a26995df88a1c38 100644 (file)
@@ -31,6 +31,8 @@
                        <channel id="switch" typeId="switch"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 24035a4211b48f724a0083c17f3a1b9c6759e8b8..af71518dff8ce0df9db467020a1d01b62e9686ec 100644 (file)
@@ -27,6 +27,8 @@
                        <channel id="step" typeId="step"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 2a41f546dc636a963bef66f28fe46103028fb254..deafab98af24d5829f31b710961a1fe776f5c1ae 100644 (file)
@@ -28,6 +28,8 @@
                        <channel id="spinningspeed" typeId="spinningspeed"/>
                </channels>
 
+               <representation-property>uid</representation-property>
+
                <config-description>
                        <parameter name="uid" type="text" required="true">
                                <label>ID</label>
index 184c3daaccec26a54b7bd5857ac64e7da04c2b8d..bdabbde84332cab0b6fe677201124f2a2b231edf 100644 (file)
@@ -13,6 +13,8 @@
                        <property name="vendor">Miele</property>
                </properties>
 
+               <representation-property>ipAddress</representation-property>
+
                <config-description>
                        <parameter name="ipAddress" type="text" required="true">
                                <context>network-address</context>
diff --git a/bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/FullyQualifiedApplianceIdentifierTest.java b/bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/FullyQualifiedApplianceIdentifierTest.java
new file mode 100644 (file)
index 0000000..f352b6c
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2010-2021 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;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+import org.openhab.core.test.java.JavaTest;
+
+/**
+ * This class provides test cases for {@link
+ * org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier}
+ *
+ * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
+ */
+public class FullyQualifiedApplianceIdentifierTest extends JavaTest {
+
+    @Test
+    public void getUidWhenConstructedFromUidReturnsUid() {
+        var identifier = new FullyQualifiedApplianceIdentifier("hdm:ZigBee:0123456789abcdef#210");
+        assertEquals("hdm:ZigBee:0123456789abcdef#210", identifier.getUid());
+    }
+
+    @Test
+    public void getUidWhenConstructedFromApplianceIdAndProtocolReturnsUid() {
+        var identifier = new FullyQualifiedApplianceIdentifier("0123456789abcdef#210", "hdm:LAN:");
+        assertEquals("hdm:LAN:0123456789abcdef#210", identifier.getUid());
+    }
+
+    @Test
+    public void getApplianceIdWhenConstructedFromUidReturnsApplianceId() {
+        var identifier = new FullyQualifiedApplianceIdentifier("hdm:ZigBee:0123456789abcdef#210");
+        assertEquals("0123456789abcdef#210", identifier.getApplianceId());
+    }
+
+    @Test
+    public void getApplianceIdWhenConstructedFromApplianceIdAndProtocolReturnsApplianceId() {
+        var identifier = new FullyQualifiedApplianceIdentifier("0123456789abcdef#210", "hdm:LAN:");
+        assertEquals("0123456789abcdef#210", identifier.getApplianceId());
+    }
+
+    @Test
+    public void getIdWhenConstructedFromUidReturnsProtocol() {
+        var identifier = new FullyQualifiedApplianceIdentifier("hdm:ZigBee:0123456789abcdef#210");
+        assertEquals("0123456789abcdef_210", identifier.getId());
+    }
+
+    @Test
+    public void getIdWhenConstructedFromApplianceIdAndProtocolReturnsProtocol() {
+        var identifier = new FullyQualifiedApplianceIdentifier("0123456789abcdef#210", "hdm:LAN:");
+        assertEquals("0123456789abcdef_210", identifier.getId());
+    }
+
+    @Test
+    public void getProtocolWhenConstructedFromUidReturnsProtocol() {
+        var identifier = new FullyQualifiedApplianceIdentifier("hdm:ZigBee:0123456789abcdef#210");
+        assertEquals("hdm:ZigBee:", identifier.getProtocol());
+    }
+
+    @Test
+    public void getProtocolWhenConstructedFromApplianceIdAndProtocolReturnsProtocol() {
+        var identifier = new FullyQualifiedApplianceIdentifier("0123456789abcdef#210", "hdm:LAN:");
+        assertEquals("hdm:LAN:", identifier.getProtocol());
+    }
+}