]> git.basschouten.com Git - openhab-addons.git/blob
57f872640cf54ca1754286175478b7716946ee94
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.miele.internal.handler;
14
15 import static org.openhab.binding.miele.internal.MieleBindingConstants.MIELE_DEVICE_CLASS_WASHING_MACHINE;
16 import static org.openhab.binding.miele.internal.MieleBindingConstants.POWER_CONSUMPTION_CHANNEL_ID;
17 import static org.openhab.binding.miele.internal.MieleBindingConstants.WATER_CONSUMPTION_CHANNEL_ID;
18
19 import java.math.BigDecimal;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
23 import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
24 import org.openhab.core.i18n.LocaleProvider;
25 import org.openhab.core.i18n.TimeZoneProvider;
26 import org.openhab.core.i18n.TranslationProvider;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.library.types.QuantityType;
29 import org.openhab.core.library.unit.Units;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.RefreshType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.gson.JsonElement;
38
39 /**
40  * The {@link WashingMachineHandler} is responsible for handling commands,
41  * which are sent to one of the channels
42  *
43  * @author Karel Goderis - Initial contribution
44  * @author Kai Kreuzer - fixed handling of REFRESH commands
45  * @author Martin Lepsy - fixed handling of empty JSON results
46  * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN), added power/water consumption channels
47  **/
48 @NonNullByDefault
49 public class WashingMachineHandler extends MieleApplianceHandler<WashingMachineChannelSelector>
50         implements ExtendedDeviceStateListener {
51
52     private static final int POWER_CONSUMPTION_BYTE_POSITION = 51;
53     private static final int WATER_CONSUMPTION_BYTE_POSITION = 53;
54     private static final int EXTENDED_STATE_MIN_SIZE_BYTES = 54;
55
56     private final Logger logger = LoggerFactory.getLogger(WashingMachineHandler.class);
57
58     public WashingMachineHandler(Thing thing, TranslationProvider i18nProvider, LocaleProvider localeProvider,
59             TimeZoneProvider timeZoneProvider) {
60         super(thing, i18nProvider, localeProvider, timeZoneProvider, WashingMachineChannelSelector.class,
61                 MIELE_DEVICE_CLASS_WASHING_MACHINE);
62     }
63
64     @Override
65     public void handleCommand(ChannelUID channelUID, Command command) {
66         super.handleCommand(channelUID, command);
67
68         String channelID = channelUID.getId();
69         String applianceId = this.applianceId;
70         if (applianceId == null) {
71             logger.warn("Command '{}' failed, appliance id is unknown", command);
72             return;
73         }
74
75         WashingMachineChannelSelector selector = (WashingMachineChannelSelector) getValueSelectorFromChannelID(
76                 channelID);
77         JsonElement result = null;
78
79         try {
80             switch (selector) {
81                 case SWITCH: {
82                     MieleBridgeHandler bridgeHandler = getMieleBridgeHandler();
83                     if (bridgeHandler == null) {
84                         logger.warn("Command '{}' failed, missing bridge handler", command);
85                         return;
86                     }
87                     if (command.equals(OnOffType.ON)) {
88                         result = bridgeHandler.invokeOperation(applianceId, modelID, "start");
89                     } else if (command.equals(OnOffType.OFF)) {
90                         result = bridgeHandler.invokeOperation(applianceId, modelID, "stop");
91                     }
92                     break;
93                 }
94                 default: {
95                     if (!(command instanceof RefreshType)) {
96                         logger.debug("{} is a read-only channel that does not accept commands",
97                                 selector.getChannelID());
98                     }
99                 }
100             }
101             // process result
102             if (result != null && isResultProcessable(result)) {
103                 logger.debug("Result of operation is {}", result.getAsString());
104             }
105         } catch (IllegalArgumentException e) {
106             logger.warn(
107                     "An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
108                     channelID, command.toString());
109         } catch (MieleRpcException e) {
110             Throwable cause = e.getCause();
111             if (cause == null) {
112                 logger.warn("An error occurred while trying to invoke operation: {}", e.getMessage());
113             } else {
114                 logger.warn("An error occurred while trying to invoke operation: {} -> {}", e.getMessage(),
115                         cause.getMessage());
116             }
117         }
118     }
119
120     @Override
121     public void onAppliancePropertyChanged(DeviceProperty dp) {
122         super.onAppliancePropertyChanged(dp);
123         updateSwitchStartStopFromState(dp);
124     }
125
126     public void onApplianceExtendedStateChanged(byte[] extendedDeviceState) {
127         if (extendedDeviceState.length < EXTENDED_STATE_MIN_SIZE_BYTES) {
128             logger.debug("Insufficient extended state data to extract consumption values: {}", extendedDeviceState);
129             return;
130         }
131
132         BigDecimal kiloWattHoursTenths = BigDecimal
133                 .valueOf(extendedDeviceState[POWER_CONSUMPTION_BYTE_POSITION] & 0xff);
134         var kiloWattHours = new QuantityType<>(kiloWattHoursTenths.divide(BigDecimal.valueOf(10)), Units.KILOWATT_HOUR);
135         updateExtendedState(POWER_CONSUMPTION_CHANNEL_ID, kiloWattHours);
136
137         var litres = new QuantityType<>(BigDecimal.valueOf(extendedDeviceState[WATER_CONSUMPTION_BYTE_POSITION] & 0xff),
138                 Units.LITRE);
139         updateExtendedState(WATER_CONSUMPTION_CHANNEL_ID, litres);
140     }
141 }