diff --git a/bundles/org.openhab.binding.miele/README.md b/bundles/org.openhab.binding.miele/README.md index 3856a68815e0b..0c72e1bf27bc9 100644 --- a/bundles/org.openhab.binding.miele/README.md +++ b/bundles/org.openhab.binding.miele/README.md @@ -128,15 +128,15 @@ Channels available for each appliance type are listed below. | Program | Description | |---------|-------------------------------------| -| 26 | Pots & Pans | -| 27 | Clean Machine | -| 28 | Economy | +| 26 | Intensive | +| 27 | Maintenance programme | +| 28 | ECO | | 30 | Normal | -| 32 | Sensor Wash | -| 34 | Energy Saver | -| 35 | China & Crystal | +| 32 | Automatic | +| 34 | SolarSave | +| 35 | Gentle | | 36 | Extra Quiet | -| 37 | SaniWash | +| 37 | Hygiene | | 38 | QuickPowerWash | | 42 | Tall items | @@ -282,6 +282,7 @@ See oven. | Program | Description | |---------|-------------------------------------| | 10 | Automatic Plus | +| 20 | Cottons | | 23 | Cottons hygiene | | 30 | Minimum iron | | 31 | Gentle minimum iron | @@ -314,11 +315,11 @@ See oven. | 513 | 1 | Programme running | | 514 | 2 | Drying | | 515 | 3 | Drying Machine iron | -| 516 | 4 | Drying Hand iron (1) | +| 516 | 4 | Drying Hand iron (2) | | 517 | 5 | Drying Normal | | 518 | 6 | Drying Normal+ | | 519 | 7 | Cooling down | -| 520 | 8 | Drying Hand iron (2) | +| 520 | 8 | Drying Hand iron (1) | | 522 | 10 | Finished | #### Washing Machine @@ -338,7 +339,7 @@ See oven. | finish | DateTime | Read | Time to finish the program running on the appliance | | door | Contact | Read | Current state of the door of the appliance | | switch | Switch | Write | Switch the appliance on or off | -| target | Number:Temperature | Read | Temperature of the selected program | +| target | Number:Temperature | Read | Temperature of the selected program (10 °C = cold) | | spinningspeed | String | Read | Spinning speed in the program running on the appliance | | powerConsumption | Number:Power | Read | Power consumption by the currently running program on the appliance | | waterConsumption | Number:Volume | Read | Water consumption by the currently running program on the appliance | diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceMetaData.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceMetaData.java new file mode 100644 index 0000000000000..9d84b350cb104 --- /dev/null +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceMetaData.java @@ -0,0 +1,46 @@ +/** + * 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 java.util.Map.Entry; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * The {@link DeviceMetaData} class represents the Metadata node in the response JSON. + * + * @author Jacob Laursen - Initial contribution + */ +public class DeviceMetaData { + public String Filter; + public String description; + public String LocalizedID; + public String LocalizedValue; + public JsonObject MieleEnum; + public String access; + + public String getMieleEnum(String s) { + if (this.MieleEnum == null) { + return null; + } + + for (Entry enumEntry : this.MieleEnum.entrySet()) { + if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { + return enumEntry.getKey(); + } + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceUtil.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceUtil.java index c80b28d38f0d4..31e168fc75871 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceUtil.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/DeviceUtil.java @@ -12,9 +12,13 @@ */ package org.openhab.binding.miele.internal; +import static org.openhab.binding.miele.internal.MieleBindingConstants.*; + import java.nio.charset.StandardCharsets; +import java.util.Map; import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.SIUnits; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; @@ -28,6 +32,15 @@ public class DeviceUtil { private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII); private static final String TEMPERATURE_UNDEFINED = "32768"; + private static final String TEMPERATURE_COLD = "-32760"; + private static final String TEXT_PREFIX = "miele."; + + private static final Map states = Map.ofEntries(Map.entry("1", "off"), Map.entry("2", "stand-by"), + Map.entry("3", "programmed"), Map.entry("4", "waiting-to-start"), Map.entry("5", "running"), + Map.entry("6", "paused"), Map.entry("7", "end"), Map.entry("8", "failure"), Map.entry("9", "abort"), + Map.entry("10", "idle"), Map.entry("11", "rinse-hold"), Map.entry("12", "service"), + Map.entry("13", "super-freezing"), Map.entry("14", "super-cooling"), Map.entry("15", "super-heating"), + Map.entry("144", "default"), Map.entry("145", "locked"), Map.entry("255", "not-connected")); /** * Convert byte array to hex representation. @@ -60,7 +73,59 @@ public static State getTemperatureState(String s) throws NumberFormatException { if (TEMPERATURE_UNDEFINED.equals(s)) { return UnDefType.UNDEF; } + if (TEMPERATURE_COLD.equals(s)) { + return new QuantityType<>(10, SIUnits.CELSIUS); + } int temperature = Integer.parseInt(s); return new QuantityType<>(temperature, SIUnits.CELSIUS); } + + /** + * Get state text for provided string taking into consideration {@link DeviceMetaData} + * as well as built-in/translated strings. + */ + public static State getStateTextState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return getTextState(s, dmd, translationProvider, states, MISSING_STATE_TEXT_PREFIX, ""); + } + + /** + * Get text for provided string taking into consideration {@link DeviceMetaData} + * as well as built-in/translated strings. + * + * @param s Raw string to be processed + * @param dmd {@link DeviceMetaData} possibly containing LocalizedValue and/or enum from gateway + * @param translationProvider {@link MieleTranslationProvider} for localization support + * @param valueMap Map of numeric values with corresponding text keys + * @param propertyPrefix Property prefix appended to text key (including dot) + * @param appliancePrefix Appliance prefix appended to text key (including dot) + * @return Text string as State + */ + public static State getTextState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider, + Map valueMap, String propertyPrefix, String appliancePrefix) { + if ("0".equals(s)) { + return UnDefType.UNDEF; + } + + String gatewayText = null; + if (dmd != null) { + if (dmd.LocalizedValue != null && !dmd.LocalizedValue.isEmpty()) { + gatewayText = dmd.LocalizedValue; + } else { + gatewayText = dmd.getMieleEnum(s); + } + } + + String value = valueMap.get(s); + if (value != null) { + String key = TEXT_PREFIX + propertyPrefix + appliancePrefix + value; + return new StringType( + translationProvider.getText(key, gatewayText != null ? gatewayText : propertyPrefix + s)); + } + + if (gatewayText != null) { + return new StringType(gatewayText); + } + + return new StringType(propertyPrefix + s); + } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java index 0ac74412f827b..65e693f031c90 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java @@ -97,12 +97,21 @@ public class MieleBindingConstants { public static final int STATE_NOT_CONNECTED = 255; // Miele missing string prefixes + public static final String MISSING_STATE_TEXT_PREFIX = "state."; public static final String MISSING_PROGRAM_TEXT_PREFIX = "program."; public static final String MISSING_PHASE_TEXT_PREFIX = "phase."; + // Miele appliance localization text prefixes + public static final String MIELE_COFFEE_MACHINE_TEXT_PREFIX = "coffeemachine."; + public static final String MIELE_DISHWASHER_TEXT_PREFIX = "dishwasher."; + public static final String MIELE_OVEN_TEXT_PREFIX = "oven."; + public static final String MIELE_TUMBLE_DRYER_TEXT_PREFIX = "tumbledryer."; + public static final String MIELE_WASHING_MACHINE_TEXT_PREFIX = "washingmachine."; + // Bridge config properties public static final String HOST = "ipAddress"; public static final String INTERFACE = "interface"; public static final String USER_NAME = "userName"; public static final String PASSWORD = "password"; + public static final String LANGUAGE = "language"; } 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 4754db07a39b8..e824716f912b6 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 @@ -35,6 +35,8 @@ 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.TranslationProvider; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; @@ -43,7 +45,10 @@ 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; +import org.osgi.service.component.annotations.Reference; /** * The {@link MieleHandlerFactory} is responsible for creating things and thing @@ -59,8 +64,18 @@ public class MieleHandlerFactory extends BaseThingHandlerFactory { MieleApplianceHandler.SUPPORTED_THING_TYPES.stream()) .collect(Collectors.toSet()); + private final TranslationProvider i18nProvider; + private final LocaleProvider localeProvider; + private Map> discoveryServiceRegs = new HashMap<>(); + @Activate + public MieleHandlerFactory(final @Reference TranslationProvider i18nProvider, + final @Reference LocaleProvider localeProvider, ComponentContext componentContext) { + this.i18nProvider = i18nProvider; + this.localeProvider = localeProvider; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -89,31 +104,31 @@ protected ThingHandler createHandler(Thing thing) { return handler; } else if (MieleApplianceHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { if (thing.getThingTypeUID().equals(THING_TYPE_HOOD)) { - return new HoodHandler(thing); + return new HoodHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_FRIDGEFREEZER)) { - return new FridgeFreezerHandler(thing); + return new FridgeFreezerHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_FRIDGE)) { - return new FridgeHandler(thing); + return new FridgeHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_OVEN)) { - return new OvenHandler(thing); + return new OvenHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_HOB)) { - return new HobHandler(thing); + return new HobHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_WASHINGMACHINE)) { - return new WashingMachineHandler(thing); + return new WashingMachineHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_DRYER)) { - return new TumbleDryerHandler(thing); + return new TumbleDryerHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_DISHWASHER)) { - return new DishWasherHandler(thing); + return new DishWasherHandler(thing, i18nProvider, localeProvider); } if (thing.getThingTypeUID().equals(THING_TYPE_COFFEEMACHINE)) { - return new CoffeeMachineHandler(thing); + return new CoffeeMachineHandler(thing, i18nProvider, localeProvider); } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleTranslationProvider.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleTranslationProvider.java new file mode 100644 index 0000000000000..fc46299cd37df --- /dev/null +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleTranslationProvider.java @@ -0,0 +1,60 @@ +/** + * 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 java.util.Locale; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; + +/** + * {@link MieleTranslationProvider} provides i18n message lookup + * + * @author Jacob Laursen - Initial contribution + */ +@NonNullByDefault +public class MieleTranslationProvider { + + private final Bundle bundle; + private final TranslationProvider i18nProvider; + private final LocaleProvider localeProvider; + @Nullable + private final Locale locale; + + public MieleTranslationProvider(TranslationProvider i18nProvider, LocaleProvider localeProvider) { + this.bundle = FrameworkUtil.getBundle(this.getClass()); + this.i18nProvider = i18nProvider; + this.localeProvider = localeProvider; + this.locale = null; + } + + public MieleTranslationProvider(TranslationProvider i18nProvider, LocaleProvider localeProvider, Locale locale) { + this.bundle = FrameworkUtil.getBundle(this.getClass()); + this.i18nProvider = i18nProvider; + this.localeProvider = localeProvider; + this.locale = locale; + } + + public String getText(String key, String defaultText, @Nullable Object... arguments) { + String text = i18nProvider.getText(bundle, key, defaultText, + locale != null ? locale : localeProvider.getLocale(), arguments); + if (text == null) { + return defaultText; + } + return text; + } +} diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceChannelSelector.java index 9ed9a638d2046..ed58dc4ed6f84 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceChannelSelector.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.miele.internal.handler; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceMetaData; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.types.State; /** @@ -51,6 +52,17 @@ public interface ApplianceChannelSelector { */ boolean isExtendedState(); + /** + * Returns a State for the given string, taking into + * account the metadata provided as well as text + * translations for corresponding numeric values. + * + * @param s - the value to be used to instantiate the State + * @param dmd - the device meta data + * @param translationProvider {@link MieleTranslationProvider} instance + */ + State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider); + /** * Returns a State for the given string, taking into * account the metadata provided. The meta data is sent by diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java index bde856833f8b1..f6b00d5cc1e1b 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java @@ -17,9 +17,10 @@ import java.lang.reflect.Method; import java.util.Collections; import java.util.Map; -import java.util.Map.Entry; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceUtil; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OpenClosedType; @@ -30,8 +31,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for coffee machines * @@ -42,35 +41,46 @@ public enum CoffeeMachineChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { - State state = getTextState(s, dmd, programs, MISSING_PROGRAM_TEXT_PREFIX); + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getTextState(s, dmd, translationProvider, programs, MISSING_PROGRAM_TEXT_PREFIX, + MIELE_COFFEE_MACHINE_TEXT_PREFIX); if (state != null) { return state; } - return super.getState(s, dmd); + return super.getState(s, dmd, translationProvider); } }, PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false), PROGRAMTYPE("programType", "type", StringType.class, false), PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { - State state = getTextState(s, dmd, phases, MISSING_PHASE_TEXT_PREFIX); + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX, + MIELE_COFFEE_MACHINE_TEXT_PREFIX); if (state != null) { return state; } - return super.getState(s, dmd); + return super.getState(s, dmd, translationProvider); } }, PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false), // lightingStatus signalFailure signalInfo DOOR("signalDoor", "door", OpenClosedType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { if ("true".equals(s)) { return getState("OPEN"); } @@ -128,10 +138,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -158,34 +173,4 @@ public State getState(String s) { return null; } - - public State getTextState(String s, DeviceMetaData dmd, Map valueMap, String prefix) { - if ("0".equals(s)) { - return UnDefType.UNDEF; - } - - if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) { - String text = valueMap.get(s); - if (text != null) { - return getState(text); - } - if (dmd == null || dmd.LocalizedValue == null) { - return getState(prefix + s); - } - } - - return null; - } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java index cff9f134c5cc7..a1d94851971dd 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java @@ -15,6 +15,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID; import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_COFFEE_SYSTEM; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -37,8 +39,9 @@ public class CoffeeMachineHandler extends MieleApplianceHandler programs = Map.ofEntries(entry("26", "Pots & Pans"), - entry("27", "Clean Machine"), entry("28", "Economy"), entry("30", "Normal"), entry("32", "Sensor Wash"), - entry("34", "Energy Saver"), entry("35", "China & Crystal"), entry("36", "Extra Quiet"), - entry("37", "SaniWash"), entry("38", "QuickPowerWash"), entry("42", "Tall items")); + private static final Map programs = Map.ofEntries(entry("26", "intensive"), + entry("27", "maintenance-programme"), entry("28", "eco"), entry("30", "normal"), entry("32", "automatic"), + entry("34", "solarsave"), entry("35", "gentle"), entry("36", "extra-quiet"), entry("37", "hygiene"), + entry("38", "quickpowerwash"), entry("42", "tall-items")); - private static final Map phases = Map.ofEntries(entry("2", "Pre-Wash"), entry("3", "Main Wash"), - entry("4", "Rinses"), entry("6", "Final rinse"), entry("7", "Drying"), entry("8", "Finished")); + private static final Map phases = Map.ofEntries(entry("2", "pre-wash"), entry("3", "main-wash"), + entry("4", "rinses"), entry("6", "final-rinse"), entry("7", "drying"), entry("8", "finished")); private final String mieleID; private final String channelID; @@ -198,10 +208,15 @@ public boolean isExtendedState() { return isExtendedState; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -228,34 +243,4 @@ public State getState(String s) { return null; } - - public State getTextState(String s, DeviceMetaData dmd, Map valueMap, String prefix) { - if ("0".equals(s)) { - return UnDefType.UNDEF; - } - - if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) { - String text = valueMap.get(s); - if (text != null) { - return getState(text); - } - if (dmd == null || dmd.LocalizedValue == null) { - return getState(prefix + s); - } - } - - return null; - } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ExtendedDeviceStateListener.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ExtendedDeviceStateListener.java index f34623d677890..df5ec2b5bed3a 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ExtendedDeviceStateListener.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ExtendedDeviceStateListener.java @@ -16,7 +16,7 @@ * Appliance handlers can implement the {@link ExtendedDeviceStateListener} interface * to extract additional information from the ExtendedDeviceState property. * - * @author Jacob Laursen - Added power/water consumption channels + * @author Jacob Laursen - Initial contribution */ public interface ExtendedDeviceStateListener { void onApplianceExtendedStateChanged(byte[] extendedDeviceState); diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java index c97cffd0fc527..7d90b846a940b 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java @@ -15,10 +15,10 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*; import java.lang.reflect.Method; -import java.util.Map.Entry; +import org.openhab.binding.miele.internal.DeviceMetaData; import org.openhab.binding.miele.internal.DeviceUtil; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OpenClosedType; @@ -30,8 +30,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for fridges * @@ -42,25 +40,34 @@ public enum FridgeChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), SUPERCOOL(null, SUPERCOOL_CHANNEL_ID, OnOffType.class, false), FRIDGECURRENTTEMP("currentTemperature", "current", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, FRIDGETARGETTEMP("targetTemperature", "target", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, DOOR("signalDoor", "door", OpenClosedType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { if ("true".equals(s)) { return getState("OPEN"); } @@ -113,10 +120,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -152,16 +164,4 @@ public State getTemperatureState(String s) { return UnDefType.UNDEF; } } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerChannelSelector.java index 14d332dc0a1dc..d81db220b288d 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerChannelSelector.java @@ -15,10 +15,10 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*; import java.lang.reflect.Method; -import java.util.Map.Entry; +import org.openhab.binding.miele.internal.DeviceMetaData; import org.openhab.binding.miele.internal.DeviceUtil; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OpenClosedType; @@ -30,8 +30,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for fridges with * a freezer compartment @@ -43,7 +41,16 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), FREEZERSTATE("freezerState", "freezerstate", StringType.class, false), FRIDGESTATE("fridgeState", "fridgestate", StringType.class, false), @@ -51,32 +58,32 @@ public enum FridgeFreezerChannelSelector implements ApplianceChannelSelector { SUPERFREEZE(null, SUPERFREEZE_CHANNEL_ID, OnOffType.class, false), FREEZERCURRENTTEMP("freezerCurrentTemperature", "freezercurrent", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, FREEZERTARGETTEMP("freezerTargetTemperature", "freezertarget", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, FRIDGECURRENTTEMP("fridgeCurrentTemperature", "fridgecurrent", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, FRIDGETARGETTEMP("fridgeTargetTemperature", "fridgetarget", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, DOOR("signalDoor", "door", OpenClosedType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { if ("true".equals(s)) { return getState("OPEN"); } @@ -130,10 +137,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -169,16 +181,4 @@ public State getTemperatureState(String s) { return UnDefType.UNDEF; } } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java index be9d5926cfbd1..82be8695190a2 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java @@ -15,6 +15,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -37,8 +39,9 @@ public class FridgeFreezerHandler extends MieleApplianceHandler private final Logger logger = LoggerFactory.getLogger(FridgeHandler.class); - public FridgeHandler(Thing thing) { - super(thing, FridgeChannelSelector.class, MIELE_DEVICE_CLASS_FRIDGE); + public FridgeHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) { + super(thing, i18nProvider, localeProvider, FridgeChannelSelector.class, MIELE_DEVICE_CLASS_FRIDGE); } @Override diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobChannelSelector.java index abe82e7c86d65..9080efcae75c3 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobChannelSelector.java @@ -15,9 +15,10 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*; import java.lang.reflect.Method; -import java.util.Map.Entry; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceUtil; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.StringType; import org.openhab.core.types.State; @@ -25,8 +26,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for hobs * @@ -37,13 +36,22 @@ public enum HobChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), PLATES("plateNumbers", "plates", DecimalType.class, true), PLATE1_POWER("plate1PowerStep", "plate1power", DecimalType.class, false), PLATE1_HEAT("plate1RemainingHeat", "plate1heat", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { // If there is remaining heat, the device metadata contains some informative string which can not be // converted into a DecimalType. We therefore ignore the metadata and return the device property value as a // State @@ -54,7 +62,7 @@ public State getState(String s, DeviceMetaData dmd) { PLATE2_POWER("plate2PowerStep", "plate2power", DecimalType.class, false), PLATE2_HEAT("plate2RemainingHeat", "plate2heat", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getState(s); } }, @@ -62,7 +70,7 @@ public State getState(String s, DeviceMetaData dmd) { PLATE3_POWER("plate3PowerStep", "plate3power", DecimalType.class, false), PLATE3_HEAT("plate3RemainingHeat", "plate3heat", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getState(s); } }, @@ -70,7 +78,7 @@ public State getState(String s, DeviceMetaData dmd) { PLATE4_POWER("plate4PowerStep", "plate4power", DecimalType.class, false), PLATE4_HEAT("plate4RemainingHeat", "plate4heat", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getState(s); } }, @@ -78,7 +86,7 @@ public State getState(String s, DeviceMetaData dmd) { PLATE5_POWER("plate5PowerStep", "plate5power", DecimalType.class, false), PLATE5_HEAT("plate5RemainingHeat", "plate5heat", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getState(s); } }, @@ -86,7 +94,7 @@ public State getState(String s, DeviceMetaData dmd) { PLATE6_POWER("plate6PowerStep", "plate6power", DecimalType.class, false), PLATE6_HEAT("plate6RemainingHeat", "plate6heat", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getState(s); } }, @@ -131,10 +139,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -161,16 +174,4 @@ public State getState(String s) { return null; } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java index bbbde6f630030..ad6ac3efc6dc2 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java @@ -14,6 +14,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_HOB; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.types.Command; @@ -27,8 +29,8 @@ */ public class HobHandler extends MieleApplianceHandler { - public HobHandler(Thing thing) { - super(thing, HobChannelSelector.class, MIELE_DEVICE_CLASS_HOB); + public HobHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) { + super(thing, i18nProvider, localeProvider, HobChannelSelector.class, MIELE_DEVICE_CLASS_HOB); } @Override diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java index 623c9830d335c..b216bb8fe9bde 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java @@ -15,9 +15,10 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*; import java.lang.reflect.Method; -import java.util.Map.Entry; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceUtil; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; @@ -27,8 +28,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for ventilation hoods * @@ -39,13 +38,22 @@ public enum HoodChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), VENTILATION("ventilationPower", "ventilation", DecimalType.class, false), LIGHT("lightingStatus", "light", OnOffType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { if ("true".equals(s)) { return getState("ON"); } @@ -98,10 +106,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -128,16 +141,4 @@ public State getState(String s) { return null; } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java index 2211e0d26c848..bdc9350b3222a 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java @@ -15,6 +15,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID; import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_HOOD; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -37,8 +39,8 @@ public class HoodHandler extends MieleApplianceHandler { private final Logger logger = LoggerFactory.getLogger(HoodHandler.class); - public HoodHandler(Thing thing) { - super(thing, HoodChannelSelector.class, MIELE_DEVICE_CLASS_HOOD); + public HoodHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) { + super(thing, i18nProvider, localeProvider, HoodChannelSelector.class, MIELE_DEVICE_CLASS_HOOD); } @Override diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java index 9c84e1a912a3e..c0b4d4f9d866f 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java @@ -15,18 +15,23 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.*; import java.util.HashMap; +import java.util.IllformedLocaleException; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNull; +import org.openhab.binding.miele.internal.DeviceMetaData; import org.openhab.binding.miele.internal.DeviceUtil; import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty; import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -71,13 +76,19 @@ public abstract class MieleApplianceHandler & ApplianceChannel protected String applianceId; protected MieleBridgeHandler bridgeHandler; + protected TranslationProvider i18nProvider; + protected LocaleProvider localeProvider; + protected MieleTranslationProvider translationProvider; private Class selectorType; protected String modelID; protected Map metaDataCache = new HashMap<>(); - public MieleApplianceHandler(Thing thing, Class selectorType, String modelID) { + public MieleApplianceHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider, + Class selectorType, String modelID) { super(thing); + this.i18nProvider = i18nProvider; + this.localeProvider = localeProvider; this.selectorType = selectorType; this.modelID = modelID; } @@ -129,6 +140,25 @@ public void onBridgeConnectionResumed() { if (bridge != null && getMieleBridgeHandler() != null) { ThingStatusInfo statusInfo = bridge.getStatusInfo(); updateStatus(statusInfo.getStatus(), statusInfo.getStatusDetail(), statusInfo.getDescription()); + initializeTranslationProvider(bridge); + } + } + + private void initializeTranslationProvider(Bridge bridge) { + Locale locale = null; + String language = (String) bridge.getConfiguration().get(LANGUAGE); + if (language != null && !language.isBlank()) { + try { + locale = new Locale.Builder().setLanguageTag(language).build(); + } catch (IllformedLocaleException e) { + logger.error("Invalid language configured: {}", e.getMessage()); + } + } + if (locale == null) { + logger.debug("No language configured, using system language."); + this.translationProvider = new MieleTranslationProvider(i18nProvider, localeProvider); + } else { + this.translationProvider = new MieleTranslationProvider(i18nProvider, localeProvider, locale); } } @@ -240,7 +270,7 @@ protected void onAppliancePropertyChanged(DeviceProperty dp) { ChannelUID theChannelUID = new ChannelUID(getThing().getUID(), selector.getChannelID()); if (dp.Value != null) { - State state = selector.getState(dpValue, dmd); + State state = selector.getState(dpValue, dmd, this.translationProvider); logger.trace("Update state of {} with getState '{}'", theChannelUID, state); updateState(theChannelUID, state); updateRawChannel(dp.Name, dpValue); @@ -249,10 +279,11 @@ protected void onAppliancePropertyChanged(DeviceProperty dp) { } } else { logger.debug("Updating the property '{}' of '{}' to '{}'", selector.getChannelID(), - getThing().getUID(), selector.getState(dpValue, dmd).toString()); + getThing().getUID(), selector.getState(dpValue, dmd, this.translationProvider).toString()); @NonNull Map<@NonNull String, @NonNull String> properties = editProperties(); - properties.put(selector.getChannelID(), selector.getState(dpValue, dmd).toString()); + properties.put(selector.getChannelID(), + selector.getState(dpValue, dmd, this.translationProvider).toString()); updateProperties(properties); } } 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 78ea4e8bc6233..47849b1f4c590 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 @@ -31,8 +31,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.IllformedLocaleException; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Random; @@ -50,6 +52,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier; import org.openhab.core.common.NamedThreadFactory; +import org.openhab.core.config.core.Configuration; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -209,15 +212,6 @@ public class DeviceProperty { } } - public class DeviceMetaData { - public String Filter; - public String description; - public String LocalizedID; - public String LocalizedValue; - public JsonObject MieleEnum; - public String access; - } - public MieleBridgeHandler(Bridge bridge) { super(bridge); } @@ -226,31 +220,59 @@ public MieleBridgeHandler(Bridge bridge) { public void initialize() { logger.debug("Initializing the Miele bridge handler."); - if (getConfig().get(HOST) != null && getConfig().get(INTERFACE) != null) { - if (IP_PATTERN.matcher((String) getConfig().get(HOST)).matches() - && IP_PATTERN.matcher((String) getConfig().get(INTERFACE)).matches()) { - try { - url = new URL("http://" + (String) getConfig().get(HOST) + "/remote/json-rpc"); - } catch (MalformedURLException e) { - logger.debug("An exception occurred while defining an URL :'{}'", e.getMessage()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, e.getMessage()); - return; - } + if (!validateConfig(getConfig())) { + return; + } - // for future usage - no headers to be set for now - headers = new HashMap<>(); + try { + url = new URL("http://" + (String) getConfig().get(HOST) + "/remote/json-rpc"); + } catch (MalformedURLException e) { + logger.debug("An exception occurred while defining an URL :'{}'", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, e.getMessage()); + return; + } + + // for future usage - no headers to be set for now + headers = new HashMap<>(); + + onUpdate(); + lastBridgeConnectionState = false; + updateStatus(ThingStatus.UNKNOWN); + } - onUpdate(); - updateStatus(ThingStatus.UNKNOWN); - } else { + private boolean validateConfig(Configuration config) { + if (config.get(HOST) == null || ((String) config.get(HOST)).isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "@text/offline.configuration-error.ip-address-not-set"); + return false; + } + if (config.get(INTERFACE) == null || ((String) config.get(INTERFACE)).isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "@text/offline.configuration-error.ip-multicast-interface-not-set"); + return false; + } + if (!IP_PATTERN.matcher((String) config.get(HOST)).matches()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "@text/offline.configuration-error.invalid-ip-gateway [\"" + config.get(HOST) + "\"]"); + return false; + } + if (!IP_PATTERN.matcher((String) config.get(INTERFACE)).matches()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "@text/offline.configuration-error.invalid-ip-multicast-interface [\"" + config.get(INTERFACE) + + "\"]"); + return false; + } + String language = (String) config.get(LANGUAGE); + if (language != null && !language.isBlank()) { + try { + new Locale.Builder().setLanguageTag(language).build(); + } catch (IllformedLocaleException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, - "Invalid IP address for the Miele@Home gateway or multicast interface:" + getConfig().get(HOST) - + "/" + getConfig().get(INTERFACE)); + "@text/offline.configuration-error.invalid-language [\"" + language + "\"]"); + return false; } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, - "Cannot connect to the Miele gateway. host IP address or multicast interface are not set."); } + return true; } private Runnable pollingRunnable = new Runnable() { diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenChannelSelector.java index f6814a8163a9a..3bd6a1b50b1a0 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenChannelSelector.java @@ -19,11 +19,11 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; -import java.util.Map.Entry; import java.util.TimeZone; +import org.openhab.binding.miele.internal.DeviceMetaData; import org.openhab.binding.miele.internal.DeviceUtil; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; @@ -36,8 +36,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for ovens * @@ -49,25 +47,35 @@ public enum OvenChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false), PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false), PROGRAMTYPE("programType", "type", StringType.class, false), PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { - State state = getTextState(s, dmd, phases, MISSING_PHASE_TEXT_PREFIX); + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX, + MIELE_OVEN_TEXT_PREFIX); if (state != null) { return state; } - return super.getState(s, dmd); + return super.getState(s, dmd, translationProvider); } }, PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false), START_TIME("startTime", "start", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -81,7 +89,7 @@ public State getState(String s, DeviceMetaData dmd) { }, DURATION("duration", "duration", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -95,7 +103,7 @@ public State getState(String s, DeviceMetaData dmd) { }, ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -109,7 +117,7 @@ public State getState(String s, DeviceMetaData dmd) { }, FINISH_TIME("finishTime", "finish", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -123,32 +131,32 @@ public State getState(String s, DeviceMetaData dmd) { }, TARGET_TEMP("targetTemperature", "target", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, MEASURED_TEMP("measuredTemperature", "measured", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, DEVICE_TEMP_ONE("deviceTemperature1", "temp1", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, DEVICE_TEMP_TWO("deviceTemperature2", "temp2", QuantityType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getTemperatureState(s); } }, DOOR("signalDoor", "door", OpenClosedType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { if ("true".equals(s)) { return getState("OPEN"); } @@ -165,9 +173,9 @@ public State getState(String s, DeviceMetaData dmd) { private final Logger logger = LoggerFactory.getLogger(OvenChannelSelector.class); - private static final Map phases = Map.ofEntries(entry("1", "Heating"), entry("2", "Temp. hold"), - entry("3", "Door Open"), entry("4", "Pyrolysis"), entry("7", "Lighting"), entry("8", "Searing phase"), - entry("10", "Defrost"), entry("11", "Cooling down"), entry("12", "Energy save phase")); + private static final Map phases = Map.ofEntries(entry("1", "heating"), entry("2", "temp-hold"), + entry("3", "door-open"), entry("4", "pyrolysis"), entry("7", "lighting"), entry("8", "searing-phase"), + entry("10", "defrost"), entry("11", "cooling-down"), entry("12", "energy-save-phase")); private final String mieleID; private final String channelID; @@ -206,10 +214,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -245,34 +258,4 @@ public State getTemperatureState(String s) { return UnDefType.UNDEF; } } - - public State getTextState(String s, DeviceMetaData dmd, Map valueMap, String prefix) { - if ("0".equals(s)) { - return UnDefType.UNDEF; - } - - if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) { - String text = valueMap.get(s); - if (text != null) { - return getState(text); - } - if (dmd == null || dmd.LocalizedValue == null) { - return getState(prefix + s); - } - } - - return null; - } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenHandler.java index 13799659e9ad3..8f3275b26159c 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/OvenHandler.java @@ -15,6 +15,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID; import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_OVEN; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -38,8 +40,8 @@ public class OvenHandler extends MieleApplianceHandler { private final Logger logger = LoggerFactory.getLogger(OvenHandler.class); - public OvenHandler(Thing thing) { - super(thing, OvenChannelSelector.class, MIELE_DEVICE_CLASS_OVEN); + public OvenHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider) { + super(thing, i18nProvider, localeProvider, OvenChannelSelector.class, MIELE_DEVICE_CLASS_OVEN); } @Override diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java index 1a375da9e4447..b17761cfcc2d7 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java @@ -19,10 +19,11 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; -import java.util.Map.Entry; import java.util.TimeZone; -import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceMetaData; +import org.openhab.binding.miele.internal.DeviceUtil; +import org.openhab.binding.miele.internal.MieleTranslationProvider; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; @@ -34,8 +35,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.JsonElement; - /** * The {@link ApplianceChannelSelector} for tumble dryers * @@ -47,34 +46,45 @@ public enum TumbleDryerChannelSelector implements ApplianceChannelSelector { PRODUCT_TYPE("productTypeId", "productType", StringType.class, true), DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true), - STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false), + STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false) { + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getStateTextState(s, dmd, translationProvider); + if (state != null) { + return state; + } + return super.getState(s, dmd, translationProvider); + } + }, STATE(null, STATE_CHANNEL_ID, DecimalType.class, false), PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { - State state = getTextState(s, dmd, programs, MISSING_PROGRAM_TEXT_PREFIX); + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getTextState(s, dmd, translationProvider, programs, MISSING_PROGRAM_TEXT_PREFIX, + MIELE_TUMBLE_DRYER_TEXT_PREFIX); if (state != null) { return state; } - return super.getState(s, dmd); + return super.getState(s, dmd, translationProvider); } }, PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false), PROGRAMTYPE("programType", "type", StringType.class, false), PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { - State state = getTextState(s, dmd, phases, MISSING_PHASE_TEXT_PREFIX); + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + State state = DeviceUtil.getTextState(s, dmd, translationProvider, phases, MISSING_PHASE_TEXT_PREFIX, + MIELE_TUMBLE_DRYER_TEXT_PREFIX); if (state != null) { return state; } - return super.getState(s, dmd); + return super.getState(s, dmd, translationProvider); } }, PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false), START_TIME("startTime", "start", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -88,7 +98,7 @@ public State getState(String s, DeviceMetaData dmd) { }, DURATION("duration", "duration", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -102,7 +112,7 @@ public State getState(String s, DeviceMetaData dmd) { }, ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -116,7 +126,7 @@ public State getState(String s, DeviceMetaData dmd) { }, FINISH_TIME("finishTime", "finish", DateTimeType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { Date date = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0")); @@ -130,14 +140,14 @@ public State getState(String s, DeviceMetaData dmd) { }, DRYING_STEP("dryingStep", "step", DecimalType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { return getState(s); } }, DOOR("signalDoor", "door", OpenClosedType.class, false) { @Override - public State getState(String s, DeviceMetaData dmd) { + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { if ("true".equals(s)) { return getState("OPEN"); } @@ -153,20 +163,20 @@ public State getState(String s, DeviceMetaData dmd) { private final Logger logger = LoggerFactory.getLogger(TumbleDryerChannelSelector.class); - private static final Map programs = Map.ofEntries(entry("10", "Automatic Plus"), - entry("23", "Cottons hygiene"), entry("30", "Minimum iron"), entry("31", "Gentle minimum iron"), - entry("40", "Woollens handcare"), entry("50", "Delicates"), entry("60", "Warm Air"), - entry("70", "Cool air"), entry("80", "Express"), entry("90", "Cottons"), entry("100", "Gentle smoothing"), - entry("120", "Proofing"), entry("130", "Denim"), entry("131", "Gentle denim"), entry("140", "Shirts"), - entry("141", "Gentle shirts"), entry("150", "Sportswear"), entry("160", "Outerwear"), - entry("170", "Silks handcare"), entry("190", "Standard pillows"), entry("220", "Basket programme"), - entry("240", "Smoothing"), entry("65000", "Cottons, auto load control"), - entry("65001", "Minimum iron, auto load control")); - - private static final Map phases = Map.ofEntries(entry("1", "Programme running"), - entry("2", "Drying"), entry("3", "Drying Machine iron"), entry("4", "Drying Hand iron"), - entry("5", "Drying Normal"), entry("6", "Drying Normal+"), entry("7", "Cooling down"), - entry("8", "Drying Hand iron"), entry("10", "Finished")); + private static final Map programs = Map.ofEntries(entry("10", "automatic-plus"), + entry("20", "cottons"), entry("23", "cottons-hygiene"), entry("30", "minimum-iron"), + entry("31", "gentle-minimum-iron"), entry("40", "woollens-handcare"), entry("50", "delicates"), + entry("60", "warm-air"), entry("70", "cool-air"), entry("80", "express"), entry("90", "cottons-eco"), + entry("100", "gentle-smoothing"), entry("120", "proofing"), entry("130", "denim"), + entry("131", "gentle-denim"), entry("140", "shirts"), entry("141", "gentle-shirts"), + entry("150", "sportswear"), entry("160", "outerwear"), entry("170", "silks-handcare"), + entry("190", "standard-pillows"), entry("220", "basket-programme"), entry("240", "smoothing"), + entry("65000", "cottons-auto-load-control"), entry("65001", "minimum-iron-auto-load-control")); + + private static final Map phases = Map.ofEntries(entry("1", "programme-running"), + entry("2", "drying"), entry("3", "drying-machine-iron"), entry("4", "drying-hand-iron"), + entry("5", "drying-normal"), entry("6", "drying-normal-plus"), entry("7", "cooling-down"), + entry("8", "drying-hand-iron"), entry("10", "finished")); private final String mieleID; private final String channelID; @@ -206,10 +216,15 @@ public boolean isExtendedState() { return false; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -236,34 +251,4 @@ public State getState(String s) { return null; } - - public State getTextState(String s, DeviceMetaData dmd, Map valueMap, String prefix) { - if ("0".equals(s)) { - return UnDefType.UNDEF; - } - - if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) { - String text = valueMap.get(s); - if (text != null) { - return getState(text); - } - if (dmd == null || dmd.LocalizedValue == null) { - return getState(prefix + s); - } - } - - return null; - } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java index 7e56d6381fc5e..e6482af4cfef0 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java @@ -15,6 +15,8 @@ import static org.openhab.binding.miele.internal.MieleBindingConstants.APPLIANCE_ID; import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_TUMBLE_DRYER; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -38,8 +40,8 @@ public class TumbleDryerHandler extends MieleApplianceHandler programs = Map.ofEntries(entry("1", "Cottons"), entry("3", "Minimum iron"), - entry("4", "Delicates"), entry("8", "Woollens"), entry("9", "Silks"), entry("17", "Starch"), - entry("18", "Rinse"), entry("21", "Drain/Spin"), entry("22", "Curtains"), entry("23", "Shirts"), - entry("24", "Denim"), entry("27", "Proofing"), entry("29", "Sportswear"), entry("31", "Automatic Plus"), - entry("37", "Outerwear"), entry("39", "Pillows"), entry("50", "Dark Garments"), entry("53", "First wash"), - entry("75", "Steam care"), entry("76", "Freshen up"), entry("91", "Maintenance wash"), - entry("95", "Down duvets"), entry("122", "Express 20"), entry("129", "Down filled items"), - entry("133", "Cottons Eco"), entry("146", "QuickPowerWash"), entry("65532", "Mix")); + private static final Map programs = Map.ofEntries(entry("1", "cottons"), entry("3", "minimum-iron"), + entry("4", "delicates"), entry("8", "woollens"), entry("9", "silks"), entry("17", "starch"), + entry("18", "rinse"), entry("21", "drain-spin"), entry("22", "curtains"), entry("23", "shirts"), + entry("24", "denim"), entry("27", "proofing"), entry("29", "sportswear"), entry("31", "automatic-plus"), + entry("37", "outerwear"), entry("39", "pillows"), entry("50", "dark-garments"), entry("53", "first-wash"), + entry("75", "steam-care"), entry("76", "freshen-up"), entry("91", "maintenance-wash"), + entry("95", "down-duvets"), entry("122", "express-20"), entry("129", "down-filled-items"), + entry("133", "cottons-eco"), entry("146", "quickpowerwash"), entry("65532", "mix")); - private static final Map phases = Map.ofEntries(entry("1", "Pre-wash"), entry("4", "Washing"), - entry("5", "Rinses"), entry("7", "Clean"), entry("9", "Drain"), entry("10", "Spin"), - entry("11", "Anti-crease"), entry("12", "Finished")); + private static final Map phases = Map.ofEntries(entry("1", "pre-wash"), entry("4", "washing"), + entry("5", "rinses"), entry("7", "clean"), entry("9", "drain"), entry("10", "spin"), + entry("11", "anti-crease"), entry("12", "finished")); private final String mieleID; private final String channelID; @@ -224,10 +233,15 @@ public boolean isExtendedState() { return isExtendedState; } + @Override + public State getState(String s, DeviceMetaData dmd, MieleTranslationProvider translationProvider) { + return this.getState(s, dmd); + } + @Override public State getState(String s, DeviceMetaData dmd) { if (dmd != null) { - String localizedValue = getMieleEnum(s, dmd); + String localizedValue = dmd.getMieleEnum(s); if (localizedValue == null) { localizedValue = dmd.LocalizedValue; } @@ -263,34 +277,4 @@ public State getTemperatureState(String s) { return UnDefType.UNDEF; } } - - public State getTextState(String s, DeviceMetaData dmd, Map valueMap, String prefix) { - if ("0".equals(s)) { - return UnDefType.UNDEF; - } - - if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) { - String text = valueMap.get(s); - if (text != null) { - return getState(text); - } - if (dmd == null || dmd.LocalizedValue == null) { - return getState(prefix + s); - } - } - - return null; - } - - public String getMieleEnum(String s, DeviceMetaData dmd) { - if (dmd.MieleEnum != null) { - for (Entry enumEntry : dmd.MieleEnum.entrySet()) { - if (enumEntry.getValue().getAsString().trim().equals(s.trim())) { - return enumEntry.getKey(); - } - } - } - - return null; - } } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java index 4c330cb07bc82..e5b3cd9c7821b 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java @@ -19,6 +19,8 @@ import java.math.BigDecimal; +import org.openhab.core.i18n.LocaleProvider; +import org.openhab.core.i18n.TranslationProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.unit.Units; @@ -49,8 +51,9 @@ public class WashingMachineHandler extends MieleApplianceHandler - Temperature of the selected program + Temperature of the selected program (10 °C = cold) 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 58d9ca23cbac4..2063c0d4149da 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 @@ -38,6 +38,10 @@ Password for the registered Miele@home user. + + + Language for state, program and phase texts. Leave blank for system language. + diff --git a/bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/DeviceUtilTest.java b/bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/DeviceUtilTest.java index d159dd5416f90..61599c5d60573 100644 --- a/bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/DeviceUtilTest.java +++ b/bundles/org.openhab.binding.miele/src/test/java/org/openhab/binding/miele/internal/DeviceUtilTest.java @@ -13,6 +13,8 @@ package org.openhab.binding.miele.internal; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; import org.openhab.core.library.types.QuantityType; @@ -58,6 +60,11 @@ public void getTemperatureStateMagicValueReturnsUndefined() throws NumberFormatE assertEquals(UnDefType.UNDEF, DeviceUtil.getTemperatureState("32768")); } + @Test + public void getTemperatureStateColdValueReturns10Degrees() throws NumberFormatException { + assertEquals(new QuantityType<>(10, SIUnits.CELSIUS), DeviceUtil.getTemperatureState("-32760")); + } + @Test public void getTemperatureStateNonNumericValueThrowsNumberFormatException() { assertThrows(NumberFormatException.class, () -> DeviceUtil.getTemperatureState("A")); @@ -67,4 +74,28 @@ public void getTemperatureStateNonNumericValueThrowsNumberFormatException() { public void getTemperatureStateNullValueThrowsNumberFormatException() { assertThrows(NumberFormatException.class, () -> DeviceUtil.getTemperatureState(null)); } + + @Test + public void getStateTextStateProviderHasPrecedence() { + assertEquals("I brug", this.getStateTextState("5", "Running", "miele.state.running", "I brug")); + } + + @Test + public void getStateTextStateGatewayTextIsReturnedWhenKeyIsUnknown() { + assertEquals("Running", this.getStateTextState("-1", "Running", "key.unknown", "I brug")); + } + + @Test + public void getStateTextStateKeyIsReturnedWhenUnknownByGatewayAndProvider() { + assertEquals("state.99", this.getStateTextState("99", null, "key.unknown", "I brug")); + } + + private String getStateTextState(String value, String localizedValue, String mockedKey, String mockedValue) { + var metaData = new DeviceMetaData(); + metaData.LocalizedValue = localizedValue; + var translationProvider = mock(MieleTranslationProvider.class); + when(translationProvider.getText(mockedKey, metaData.LocalizedValue)).thenReturn(mockedValue); + + return DeviceUtil.getStateTextState(value, metaData, translationProvider).toString(); + } }