2 * Copyright (c) 2010-2021 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.miele.internal.handler;
15 import static java.util.Map.entry;
16 import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
18 import java.lang.reflect.Method;
19 import java.text.SimpleDateFormat;
20 import java.util.Date;
22 import java.util.Map.Entry;
23 import java.util.TimeZone;
25 import org.openhab.binding.miele.internal.DeviceUtil;
26 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceMetaData;
27 import org.openhab.core.library.types.DateTimeType;
28 import org.openhab.core.library.types.DecimalType;
29 import org.openhab.core.library.types.OnOffType;
30 import org.openhab.core.library.types.OpenClosedType;
31 import org.openhab.core.library.types.QuantityType;
32 import org.openhab.core.library.types.StringType;
33 import org.openhab.core.types.State;
34 import org.openhab.core.types.Type;
35 import org.openhab.core.types.UnDefType;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.gson.JsonElement;
42 * The {@link ApplianceChannelSelector} for washing machines
44 * @author Karel Goderis - Initial contribution
45 * @author Kai Kreuzer - Changed START_TIME to DateTimeType
46 * @author Jacob Laursen - Added power/water consumption channels, UoM for temperatures, raw channels
48 public enum WashingMachineChannelSelector implements ApplianceChannelSelector {
50 PRODUCT_TYPE("productTypeId", "productType", StringType.class, true, false),
51 DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true, false),
52 STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false, false),
53 STATE(null, STATE_CHANNEL_ID, DecimalType.class, false, false),
54 PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false, false) {
56 public State getState(String s, DeviceMetaData dmd) {
57 State state = getTextState(s, dmd, programs, MISSING_PROGRAM_TEXT_PREFIX);
61 return super.getState(s, dmd);
64 PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false, false),
65 PROGRAMTYPE("programType", "type", StringType.class, false, false),
66 PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false, false) {
68 public State getState(String s, DeviceMetaData dmd) {
69 State state = getTextState(s, dmd, phases, MISSING_PHASE_TEXT_PREFIX);
73 return super.getState(s, dmd);
76 PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false, false),
77 START_TIME("startTime", "start", DateTimeType.class, false, false) {
79 public State getState(String s, DeviceMetaData dmd) {
80 Date date = new Date();
81 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
82 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
84 date.setTime(Long.valueOf(s) * 60000);
85 } catch (Exception e) {
88 return getState(dateFormatter.format(date));
91 DURATION("duration", "duration", DateTimeType.class, false, false) {
93 public State getState(String s, DeviceMetaData dmd) {
94 Date date = new Date();
95 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
96 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
98 date.setTime(Long.valueOf(s.trim()) * 60000);
99 } catch (Exception e) {
102 return getState(dateFormatter.format(date));
105 ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false, false) {
107 public State getState(String s, DeviceMetaData dmd) {
108 Date date = new Date();
109 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
110 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
112 date.setTime(Long.valueOf(s) * 60000);
113 } catch (Exception e) {
116 return getState(dateFormatter.format(date));
119 FINISH_TIME("finishTime", "finish", DateTimeType.class, false, false) {
121 public State getState(String s, DeviceMetaData dmd) {
122 Date date = new Date();
123 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
124 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
126 date.setTime(Long.valueOf(s) * 60000);
127 } catch (Exception e) {
130 return getState(dateFormatter.format(date));
133 TARGET_TEMP("targetTemperature", "target", QuantityType.class, false, false) {
135 public State getState(String s, DeviceMetaData dmd) {
136 return getTemperatureState(s);
139 SPINNING_SPEED("spinningSpeed", "spinningspeed", StringType.class, false, false) {
141 public State getState(String s, DeviceMetaData dmd) {
143 return getState("Without spinning");
145 if ("256".equals(s)) {
146 return getState("Rinsing");
148 return getState(Integer.toString((Integer.valueOf(s))));
151 DOOR("signalDoor", "door", OpenClosedType.class, false, false) {
154 public State getState(String s, DeviceMetaData dmd) {
155 if ("true".equals(s)) {
156 return getState("OPEN");
159 if ("false".equals(s)) {
160 return getState("CLOSED");
163 return UnDefType.UNDEF;
166 SWITCH(null, "switch", OnOffType.class, false, false),
167 POWER_CONSUMPTION(EXTENDED_DEVICE_STATE_PROPERTY_NAME, POWER_CONSUMPTION_CHANNEL_ID, QuantityType.class, false,
169 WATER_CONSUMPTION(EXTENDED_DEVICE_STATE_PROPERTY_NAME, WATER_CONSUMPTION_CHANNEL_ID, QuantityType.class, false,
172 private final Logger logger = LoggerFactory.getLogger(WashingMachineChannelSelector.class);
174 private static final Map<String, String> programs = Map.ofEntries(entry("1", "Cottons"), entry("3", "Minimum iron"),
175 entry("4", "Delicates"), entry("8", "Woollens"), entry("9", "Silks"), entry("17", "Starch"),
176 entry("18", "Rinse"), entry("21", "Drain/Spin"), entry("22", "Curtains"), entry("23", "Shirts"),
177 entry("24", "Denim"), entry("27", "Proofing"), entry("29", "Sportswear"), entry("31", "Automatic Plus"),
178 entry("37", "Outerwear"), entry("39", "Pillows"), entry("50", "Dark Garments"), entry("53", "First wash"),
179 entry("75", "Steam care"), entry("76", "Freshen up"), entry("91", "Maintenance wash"),
180 entry("95", "Down duvets"), entry("122", "Express 20"), entry("129", "Down filled items"),
181 entry("133", "Cottons Eco"), entry("146", "QuickPowerWash"), entry("65532", "Mix"));
183 private static final Map<String, String> phases = Map.ofEntries(entry("1", "Pre-wash"), entry("4", "Washing"),
184 entry("5", "Rinses"), entry("7", "Clean"), entry("9", "Drain"), entry("10", "Spin"),
185 entry("11", "Anti-crease"), entry("12", "Finished"));
187 private final String mieleID;
188 private final String channelID;
189 private final Class<? extends Type> typeClass;
190 private final boolean isProperty;
191 private final boolean isExtendedState;
193 WashingMachineChannelSelector(String propertyID, String channelID, Class<? extends Type> typeClass,
194 boolean isProperty, boolean isExtendedState) {
195 this.mieleID = propertyID;
196 this.channelID = channelID;
197 this.typeClass = typeClass;
198 this.isProperty = isProperty;
199 this.isExtendedState = isExtendedState;
203 public String toString() {
208 public String getMieleID() {
213 public String getChannelID() {
218 public boolean isProperty() {
223 public boolean isExtendedState() {
224 return isExtendedState;
228 public State getState(String s, DeviceMetaData dmd) {
230 String localizedValue = getMieleEnum(s, dmd);
231 if (localizedValue == null) {
232 localizedValue = dmd.LocalizedValue;
234 if (localizedValue == null) {
238 return getState(localizedValue);
244 public State getState(String s) {
246 Method valueOf = typeClass.getMethod("valueOf", String.class);
247 State state = (State) valueOf.invoke(typeClass, s);
251 } catch (Exception e) {
252 logger.error("An exception occurred while converting '{}' into a State", s);
258 public State getTemperatureState(String s) {
260 return DeviceUtil.getTemperatureState(s);
261 } catch (NumberFormatException e) {
262 logger.warn("An exception occurred while converting '{}' into a State", s);
263 return UnDefType.UNDEF;
267 public State getTextState(String s, DeviceMetaData dmd, Map<String, String> valueMap, String prefix) {
269 return UnDefType.UNDEF;
272 if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) {
273 String text = valueMap.get(s);
275 return getState(text);
277 if (dmd == null || dmd.LocalizedValue == null) {
278 return getState(prefix + s);
285 public String getMieleEnum(String s, DeviceMetaData dmd) {
286 if (dmd.MieleEnum != null) {
287 for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) {
288 if (enumEntry.getValue().getAsString().trim().equals(s.trim())) {
289 return enumEntry.getKey();