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.handler.MieleBridgeHandler.DeviceMetaData;
26 import org.openhab.core.library.types.DateTimeType;
27 import org.openhab.core.library.types.DecimalType;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.OpenClosedType;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.types.State;
32 import org.openhab.core.types.Type;
33 import org.openhab.core.types.UnDefType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.google.gson.JsonElement;
40 * The {@link ApplianceChannelSelector} for tumble dryers
42 * @author Karel Goderis - Initial contribution
43 * @author Kai Kreuzer - Changed START_TIME to DateTimeType
44 * @author Jacob Laursen - Added raw channels
46 public enum TumbleDryerChannelSelector implements ApplianceChannelSelector {
48 PRODUCT_TYPE("productTypeId", "productType", StringType.class, true),
49 DEVICE_TYPE("mieleDeviceType", "deviceType", StringType.class, true),
50 STATE_TEXT(STATE_PROPERTY_NAME, STATE_TEXT_CHANNEL_ID, StringType.class, false),
51 STATE(null, STATE_CHANNEL_ID, DecimalType.class, false),
52 PROGRAM_TEXT(PROGRAM_ID_PROPERTY_NAME, PROGRAM_TEXT_CHANNEL_ID, StringType.class, false) {
54 public State getState(String s, DeviceMetaData dmd) {
55 State state = getTextState(s, dmd, programs, MISSING_PROGRAM_TEXT_PREFIX);
59 return super.getState(s, dmd);
62 PROGRAM(null, PROGRAM_CHANNEL_ID, DecimalType.class, false),
63 PROGRAMTYPE("programType", "type", StringType.class, false),
64 PROGRAM_PHASE_TEXT(PHASE_PROPERTY_NAME, PHASE_TEXT_CHANNEL_ID, StringType.class, false) {
66 public State getState(String s, DeviceMetaData dmd) {
67 State state = getTextState(s, dmd, phases, MISSING_PHASE_TEXT_PREFIX);
71 return super.getState(s, dmd);
74 PROGRAM_PHASE(RAW_PHASE_PROPERTY_NAME, PHASE_CHANNEL_ID, DecimalType.class, false),
75 START_TIME("startTime", "start", DateTimeType.class, false) {
77 public State getState(String s, DeviceMetaData dmd) {
78 Date date = new Date();
79 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
80 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
82 date.setTime(Long.valueOf(s) * 60000);
83 } catch (Exception e) {
86 return getState(dateFormatter.format(date));
89 DURATION("duration", "duration", DateTimeType.class, false) {
91 public State getState(String s, DeviceMetaData dmd) {
92 Date date = new Date();
93 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
94 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
96 date.setTime(Long.valueOf(s) * 60000);
97 } catch (Exception e) {
100 return getState(dateFormatter.format(date));
103 ELAPSED_TIME("elapsedTime", "elapsed", DateTimeType.class, false) {
105 public State getState(String s, DeviceMetaData dmd) {
106 Date date = new Date();
107 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
108 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
110 date.setTime(Long.valueOf(s) * 60000);
111 } catch (Exception e) {
114 return getState(dateFormatter.format(date));
117 FINISH_TIME("finishTime", "finish", DateTimeType.class, false) {
119 public State getState(String s, DeviceMetaData dmd) {
120 Date date = new Date();
121 SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
122 dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT+0"));
124 date.setTime(Long.valueOf(s) * 60000);
125 } catch (Exception e) {
128 return getState(dateFormatter.format(date));
131 DRYING_STEP("dryingStep", "step", DecimalType.class, false) {
133 public State getState(String s, DeviceMetaData dmd) {
137 DOOR("signalDoor", "door", OpenClosedType.class, false) {
140 public State getState(String s, DeviceMetaData dmd) {
141 if ("true".equals(s)) {
142 return getState("OPEN");
145 if ("false".equals(s)) {
146 return getState("CLOSED");
149 return UnDefType.UNDEF;
152 SWITCH(null, "switch", OnOffType.class, false);
154 private final Logger logger = LoggerFactory.getLogger(TumbleDryerChannelSelector.class);
156 private static final Map<String, String> programs = Map.ofEntries(entry("10", "Automatic Plus"),
157 entry("23", "Cottons hygiene"), entry("30", "Minimum iron"), entry("31", "Gentle minimum iron"),
158 entry("40", "Woollens handcare"), entry("50", "Delicates"), entry("60", "Warm Air"),
159 entry("70", "Cool air"), entry("80", "Express"), entry("90", "Cottons"), entry("100", "Gentle smoothing"),
160 entry("120", "Proofing"), entry("130", "Denim"), entry("131", "Gentle denim"), entry("140", "Shirts"),
161 entry("141", "Gentle shirts"), entry("150", "Sportswear"), entry("160", "Outerwear"),
162 entry("170", "Silks handcare"), entry("190", "Standard pillows"), entry("220", "Basket programme"),
163 entry("240", "Smoothing"), entry("65000", "Cottons, auto load control"),
164 entry("65001", "Minimum iron, auto load control"));
166 private static final Map<String, String> phases = Map.ofEntries(entry("1", "Programme running"),
167 entry("2", "Drying"), entry("3", "Drying Machine iron"), entry("4", "Drying Hand iron"),
168 entry("5", "Drying Normal"), entry("6", "Drying Normal+"), entry("7", "Cooling down"),
169 entry("8", "Drying Hand iron"), entry("10", "Finished"));
171 private final String mieleID;
172 private final String channelID;
173 private final Class<? extends Type> typeClass;
174 private final boolean isProperty;
176 TumbleDryerChannelSelector(String propertyID, String channelID, Class<? extends Type> typeClass,
177 boolean isProperty) {
178 this.mieleID = propertyID;
179 this.channelID = channelID;
180 this.typeClass = typeClass;
181 this.isProperty = isProperty;
185 public String toString() {
190 public String getMieleID() {
195 public String getChannelID() {
200 public boolean isProperty() {
205 public boolean isExtendedState() {
210 public State getState(String s, DeviceMetaData dmd) {
212 String localizedValue = getMieleEnum(s, dmd);
213 if (localizedValue == null) {
214 localizedValue = dmd.LocalizedValue;
216 if (localizedValue == null) {
220 return getState(localizedValue);
226 public State getState(String s) {
228 Method valueOf = typeClass.getMethod("valueOf", String.class);
229 State state = (State) valueOf.invoke(typeClass, s);
233 } catch (Exception e) {
234 logger.error("An exception occurred while converting '{}' into a State", s);
240 public State getTextState(String s, DeviceMetaData dmd, Map<String, String> valueMap, String prefix) {
242 return UnDefType.UNDEF;
245 if (dmd == null || dmd.LocalizedValue == null || dmd.LocalizedValue.startsWith(prefix)) {
246 String text = valueMap.get(s);
248 return getState(text);
250 if (dmd == null || dmd.LocalizedValue == null) {
251 return getState(prefix + s);
258 public String getMieleEnum(String s, DeviceMetaData dmd) {
259 if (dmd.MieleEnum != null) {
260 for (Entry<String, JsonElement> enumEntry : dmd.MieleEnum.entrySet()) {
261 if (enumEntry.getValue().getAsString().trim().equals(s.trim())) {
262 return enumEntry.getKey();