Skip to content

Commit

Permalink
[miele] Fix multicast and multi-protocol support (ZigBee/Wi-Fi) (open…
Browse files Browse the repository at this point in the history
…hab#11244)

* 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 openhab#11242

Fixes openhab#11243

Signed-off-by: Jacob Laursen <[email protected]>
  • Loading branch information
jlaur authored and thinkingstone committed Nov 7, 2021
1 parent 54ea293 commit 7c34ffb
Show file tree
Hide file tree
Showing 27 changed files with 390 additions and 147 deletions.
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@
*
* @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 {

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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -42,6 +43,7 @@
*
* @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 {

Expand Down Expand Up @@ -101,8 +103,10 @@ private void onApplianceAddedInternal(HomeDevice appliance) {
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();
Expand All @@ -113,7 +117,8 @@ private void onApplianceAddedInternal(HomeDevice appliance) {
}

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 {
Expand All @@ -132,12 +137,17 @@ public void onApplianceRemoved(HomeDevice appliance) {
}

@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
}

Expand All @@ -158,7 +168,7 @@ private ThingUID getThingUID(HomeDevice appliance) {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
*
* @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 {
Expand Down Expand Up @@ -83,8 +83,7 @@ public DiscoveryResult createResult(ServiceInfo service) {
}

return DiscoveryResultBuilder.create(uid).withProperties(properties)
.withRepresentationProperty(MieleBindingConstants.HOST).withLabel("Miele XGW3000 Gateway")
.build();
.withRepresentationProperty(MieleBindingConstants.HOST).withLabel("Miele XGW3000").build();
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -22,24 +23,33 @@
* 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,6 +32,7 @@
*
* @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> {

Expand All @@ -44,7 +47,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
Expand All @@ -54,9 +59,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,6 +33,7 @@
* @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> {

Expand All @@ -45,7 +48,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
Expand All @@ -55,9 +60,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,6 +32,7 @@
* @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> {

Expand All @@ -44,7 +47,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
Expand All @@ -54,17 +59,17 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,6 +32,7 @@
*
* @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> {

Expand All @@ -44,7 +47,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
Expand All @@ -54,15 +59,15 @@ public void handleCommand(ChannelUID channelUID, Command command) {
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;
}
Expand Down
Loading

0 comments on commit 7c34ffb

Please sign in to comment.