From 6b86dabbd972ea576fdc83fd635c5fcd96183ef5 Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Wed, 10 Jan 2024 00:03:14 +0100 Subject: [PATCH] Use localized labels for discovery results (#16250) Signed-off-by: Jacob Laursen Signed-off-by: Ciprian Pascu --- .../miele/internal/MieleHandlerFactory.java | 37 +---- .../MieleApplianceDiscoveryService.java | 154 ++++++++++-------- .../internal/handler/MieleBridgeHandler.java | 8 + .../resources/OH-INF/i18n/miele.properties | 11 +- .../main/resources/OH-INF/thing/xgw3000.xml | 2 +- 5 files changed, 108 insertions(+), 104 deletions(-) diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleHandlerFactory.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleHandlerFactory.java index 5682c72f482..e5abadfffd8 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleHandlerFactory.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleHandlerFactory.java @@ -14,9 +14,6 @@ package org.openhab.binding.miele.internal; import static org.openhab.binding.miele.internal.MieleBindingConstants.*; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -24,7 +21,6 @@ import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; -import org.openhab.binding.miele.internal.discovery.MieleApplianceDiscoveryService; import org.openhab.binding.miele.internal.handler.CoffeeMachineHandler; import org.openhab.binding.miele.internal.handler.DishwasherHandler; import org.openhab.binding.miele.internal.handler.FridgeFreezerHandler; @@ -37,7 +33,6 @@ import org.openhab.binding.miele.internal.handler.OvenHandler; import org.openhab.binding.miele.internal.handler.TumbleDryerHandler; import org.openhab.binding.miele.internal.handler.WashingMachineHandler; import org.openhab.core.config.core.Configuration; -import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.i18n.LocaleProvider; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.i18n.TranslationProvider; @@ -49,7 +44,6 @@ import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerFactory; -import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -76,10 +70,8 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory { private final LocaleProvider localeProvider; private final TimeZoneProvider timeZoneProvider; - private Map> discoveryServiceRegs = new HashMap<>(); - @Activate - public MieleHandlerFactory(@Reference final HttpClientFactory httpClientFactory, + public MieleHandlerFactory(final @Reference HttpClientFactory httpClientFactory, final @Reference TranslationProvider i18nProvider, final @Reference LocaleProvider localeProvider, final @Reference TimeZoneProvider timeZoneProvider, ComponentContext componentContext) { this.httpClient = httpClientFactory.getCommonHttpClient(); @@ -111,9 +103,7 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory { @Override protected @Nullable ThingHandler createHandler(Thing thing) { if (MieleBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { - MieleBridgeHandler handler = new MieleBridgeHandler((Bridge) thing, httpClient); - registerApplianceDiscoveryService(handler); - return handler; + return new MieleBridgeHandler((Bridge) thing, httpClient); } else if (MieleApplianceHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { if (thing.getThingTypeUID().equals(THING_TYPE_HOOD)) { return new HoodHandler(thing, i18nProvider, localeProvider, timeZoneProvider); @@ -169,27 +159,4 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory { } return thingUID; } - - private synchronized void registerApplianceDiscoveryService(MieleBridgeHandler bridgeHandler) { - MieleApplianceDiscoveryService discoveryService = new MieleApplianceDiscoveryService(bridgeHandler); - discoveryService.activate(); - this.discoveryServiceRegs.put(bridgeHandler.getThing().getUID(), - bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>())); - } - - @Override - protected synchronized void removeHandler(ThingHandler thingHandler) { - if (thingHandler instanceof MieleBridgeHandler) { - ServiceRegistration serviceReg = this.discoveryServiceRegs.remove(thingHandler.getThing().getUID()); - if (serviceReg != null) { - // remove discovery service, if bridge handler is removed - MieleApplianceDiscoveryService service = (MieleApplianceDiscoveryService) bundleContext - .getService(serviceReg.getReference()); - serviceReg.unregister(); - if (service != null) { - service.deactivate(); - } - } - } - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleApplianceDiscoveryService.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleApplianceDiscoveryService.java index ffc6f4018fe..03833f93a9d 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleApplianceDiscoveryService.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleApplianceDiscoveryService.java @@ -14,7 +14,7 @@ package org.openhab.binding.miele.internal.discovery; import static org.openhab.binding.miele.internal.MieleBindingConstants.*; -import java.util.Date; +import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,45 +27,62 @@ import org.openhab.binding.miele.internal.api.dto.HomeDevice; import org.openhab.binding.miele.internal.handler.DiscoveryListener; import org.openhab.binding.miele.internal.handler.MieleApplianceHandler; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler; -import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService; import org.openhab.core.config.discovery.DiscoveryResult; import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingUID; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ServiceScope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The {@link MieleApplianceDiscoveryService} tracks appliances that are - * associated with the Miele@Home gateway + * associated with the Miele@home gateway * * @author Karel Goderis - Initial contribution - * @author Martin Lepsy - Added protocol information in order so support WiFi devices + * @author Martin Lepsy - Added protocol information in order to support WiFi devices * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN) */ +@Component(scope = ServiceScope.PROTOTYPE, service = MieleApplianceDiscoveryService.class) @NonNullByDefault -public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements DiscoveryListener { +public class MieleApplianceDiscoveryService extends AbstractThingHandlerDiscoveryService + implements DiscoveryListener { private final Logger logger = LoggerFactory.getLogger(MieleApplianceDiscoveryService.class); - private static final int SEARCH_TIME = 60; + private static final int SEARCH_TIME_SECONDS = 60; - private MieleBridgeHandler mieleBridgeHandler; - - public MieleApplianceDiscoveryService(MieleBridgeHandler mieleBridgeHandler) { - super(MieleApplianceHandler.SUPPORTED_THING_TYPES, SEARCH_TIME, false); - this.mieleBridgeHandler = mieleBridgeHandler; + public MieleApplianceDiscoveryService() { + super(MieleBridgeHandler.class, MieleApplianceHandler.SUPPORTED_THING_TYPES, SEARCH_TIME_SECONDS, false); } - public void activate() { - mieleBridgeHandler.registerDiscoveryListener(this); + @Reference(unbind = "-") + public void bindTranslationProvider(TranslationProvider translationProvider) { + this.i18nProvider = translationProvider; + } + + @Reference(unbind = "-") + public void bindLocaleProvider(LocaleProvider localeProvider) { + this.localeProvider = localeProvider; } @Override - public void deactivate() { - removeOlderResults(new Date().getTime()); - mieleBridgeHandler.unregisterDiscoveryListener(this); + public void initialize() { + thingHandler.registerDiscoveryListener(this); + super.initialize(); + } + + @Override + public void dispose() { + super.dispose(); + removeOlderResults(Instant.now().toEpochMilli()); + thingHandler.unregisterDiscoveryListener(this); } @Override @@ -75,9 +92,9 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp @Override public void startScan() { - List appliances = mieleBridgeHandler.getHomeDevicesEmptyOnFailure(); - for (HomeDevice l : appliances) { - onApplianceAddedInternal(l); + List appliances = thingHandler.getHomeDevicesEmptyOnFailure(); + for (HomeDevice appliance : appliances) { + onApplianceAddedInternal(appliance); } } @@ -94,45 +111,49 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp private void onApplianceAddedInternal(HomeDevice appliance) { ThingUID thingUID = getThingUID(appliance); - if (thingUID != null) { - ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID(); - Map properties = new HashMap<>(9); - - FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier(); - String vendor = appliance.Vendor; - if (vendor != null) { - properties.put(Thing.PROPERTY_VENDOR, vendor); - } - properties.put(Thing.PROPERTY_MODEL_ID, appliance.getApplianceModel()); - properties.put(Thing.PROPERTY_SERIAL_NUMBER, appliance.getSerialNumber()); - properties.put(Thing.PROPERTY_FIRMWARE_VERSION, appliance.getFirmwareVersion()); - String protocolAdapterName = appliance.ProtocolAdapterName; - if (protocolAdapterName != null) { - properties.put(PROPERTY_PROTOCOL_ADAPTER, protocolAdapterName); - } - properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId()); - String deviceClass = appliance.getDeviceClass(); - if (deviceClass != null) { - properties.put(PROPERTY_DEVICE_CLASS, deviceClass); - } - String connectionType = appliance.getConnectionType(); - if (connectionType != null) { - properties.put(PROPERTY_CONNECTION_TYPE, connectionType); - } - String connectionBaudRate = appliance.getConnectionBaudRate(); - if (connectionBaudRate != null) { - properties.put(PROPERTY_CONNECTION_BAUD_RATE, connectionBaudRate); - } - - DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) - .withBridge(bridgeUID).withLabel(deviceClass != null ? deviceClass : appliance.getApplianceModel()) - .withRepresentationProperty(APPLIANCE_ID).build(); - - thingDiscovered(discoveryResult); - } else { + if (thingUID == null) { logger.debug("Discovered an unsupported appliance of vendor '{}' with id {}", appliance.Vendor, appliance.UID); + return; } + ThingUID bridgeUID = thingHandler.getThing().getUID(); + Map properties = new HashMap<>(9); + + FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier(); + String vendor = appliance.Vendor; + if (vendor != null) { + properties.put(Thing.PROPERTY_VENDOR, vendor); + } + properties.put(Thing.PROPERTY_MODEL_ID, appliance.getApplianceModel()); + properties.put(Thing.PROPERTY_SERIAL_NUMBER, appliance.getSerialNumber()); + properties.put(Thing.PROPERTY_FIRMWARE_VERSION, appliance.getFirmwareVersion()); + String protocolAdapterName = appliance.ProtocolAdapterName; + if (protocolAdapterName != null) { + properties.put(PROPERTY_PROTOCOL_ADAPTER, protocolAdapterName); + } + properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId()); + String deviceClass = appliance.getDeviceClass(); + if (deviceClass != null) { + properties.put(PROPERTY_DEVICE_CLASS, deviceClass); + } + String connectionType = appliance.getConnectionType(); + if (connectionType != null) { + properties.put(PROPERTY_CONNECTION_TYPE, connectionType); + } + String connectionBaudRate = appliance.getConnectionBaudRate(); + if (connectionBaudRate != null) { + properties.put(PROPERTY_CONNECTION_BAUD_RATE, connectionBaudRate); + } + + String label = deviceClass != null + ? "@text/discovery." + getThingTypeUidFromDeviceClass(deviceClass).getId() + ".label [\"" + + appliance.getApplianceModel() + "\"]" + : appliance.getApplianceModel(); + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) + .withBridge(bridgeUID).withLabel(label).withRepresentationProperty(APPLIANCE_ID).build(); + + thingDiscovered(discoveryResult); } @Override @@ -145,33 +166,32 @@ public class MieleApplianceDiscoveryService extends AbstractDiscoveryService imp } private @Nullable ThingUID getThingUID(HomeDevice appliance) { - ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID(); - String modelId = appliance.getDeviceClass(); + ThingUID bridgeUID = thingHandler.getThing().getUID(); + String deviceClass = appliance.getDeviceClass(); + if (deviceClass == null) { + return null; + } - if (modelId != null) { - ThingTypeUID thingTypeUID = getThingTypeUidFromModelId(modelId); + ThingTypeUID thingTypeUID = getThingTypeUidFromDeviceClass(deviceClass); - if (getSupportedThingTypes().contains(thingTypeUID)) { - return new ThingUID(thingTypeUID, bridgeUID, appliance.getApplianceIdentifier().getId()); - } else { - return null; - } + if (getSupportedThingTypes().contains(thingTypeUID)) { + return new ThingUID(thingTypeUID, bridgeUID, appliance.getApplianceIdentifier().getId()); } else { return null; } } - private ThingTypeUID getThingTypeUidFromModelId(String modelId) { + private ThingTypeUID getThingTypeUidFromDeviceClass(String deviceClass) { /* * Coffee machine CVA 6805 is reported as CoffeeSystem, but thing type is * coffeemachine. At least until it is known if any models are actually reported * as CoffeeMachine, we need this special mapping. */ - if (MIELE_DEVICE_CLASS_COFFEE_SYSTEM.equals(modelId)) { + if (MIELE_DEVICE_CLASS_COFFEE_SYSTEM.equals(deviceClass)) { return THING_TYPE_COFFEEMACHINE; } - String thingTypeId = modelId.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase(); + String thingTypeId = deviceClass.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase(); return new ThingTypeUID(BINDING_ID, thingTypeId); } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleBridgeHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleBridgeHandler.java index 3256630b87d..d5e18d17fa8 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleBridgeHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleBridgeHandler.java @@ -27,6 +27,7 @@ import java.net.URISyntaxException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; import java.util.Enumeration; import java.util.IllformedLocaleException; import java.util.Iterator; @@ -51,6 +52,7 @@ import org.openhab.binding.miele.internal.MieleGatewayCommunicationController; 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.discovery.MieleApplianceDiscoveryService; import org.openhab.binding.miele.internal.exceptions.MieleRpcException; import org.openhab.core.common.NamedThreadFactory; import org.openhab.core.config.core.Configuration; @@ -60,6 +62,7 @@ import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.BaseBridgeHandler; +import org.openhab.core.thing.binding.ThingHandlerService; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.slf4j.Logger; @@ -134,6 +137,11 @@ public class MieleBridgeHandler extends BaseBridgeHandler { schedulePollingAndEventListener(); } + @Override + public Collection> getServices() { + return Set.of(MieleApplianceDiscoveryService.class); + } + private boolean validateConfig(Configuration config) { if (config.get(HOST) == null || ((String) config.get(HOST)).isBlank()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, diff --git a/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/i18n/miele.properties b/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/i18n/miele.properties index 9adee11d2ad..96c1c92037e 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/i18n/miele.properties +++ b/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/i18n/miele.properties @@ -39,7 +39,7 @@ thing-type.miele.washingmachine.description = This is a Miele@home compatible wa thing-type.miele.washingmachine.channel.target.label = Temperature thing-type.miele.washingmachine.channel.target.description = Temperature of the selected program (10 °C = cold) thing-type.miele.xgw3000.label = Miele XGW3000 -thing-type.miele.xgw3000.description = The Miele bridge represents the Miele@home XGW3000 gateway. +thing-type.miele.xgw3000.description = The Miele bridge represents the Miele@home XGW 3000 gateway. # thing types config @@ -136,6 +136,15 @@ offline.configuration-error.uid-not-set = Appliance ID is not set # discovery result discovery.xgw3000.label = Miele XGW 3000 +discovery.coffeemachine.label = Coffee Machine ({0}) +discovery.dishwasher.label = Dishwasher ({0}) +discovery.fridge.label = Fridge ({0}) +discovery.fridgefreezer.label = Fridge Freezer ({0}) +discovery.hob.label = Hob ({0}) +discovery.hood.label = Hood ({0}) +discovery.oven.label = Oven ({0}) +discovery.tumbledryer.label = Tumbledryer ({0}) +discovery.washingmachine.label = Washing Machine ({0}) # miele states diff --git a/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/xgw3000.xml b/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/xgw3000.xml index 2063c0d4149..345c5878b15 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/xgw3000.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/OH-INF/thing/xgw3000.xml @@ -7,7 +7,7 @@ - The Miele bridge represents the Miele@home XGW3000 gateway. + The Miele bridge represents the Miele@home XGW 3000 gateway. Miele