2 * Copyright (c) 2010-2024 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.draytonwiser.internal.handler;
15 import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
17 import java.util.List;
19 import javax.measure.quantity.Time;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
24 import org.openhab.binding.draytonwiser.internal.handler.HotWaterHandler.HotWaterData;
25 import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
26 import org.openhab.binding.draytonwiser.internal.model.HotWaterDTO;
27 import org.openhab.binding.draytonwiser.internal.model.SystemDTO;
28 import org.openhab.core.library.types.DecimalType;
29 import org.openhab.core.library.types.OnOffType;
30 import org.openhab.core.library.types.QuantityType;
31 import org.openhab.core.library.unit.Units;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.types.Command;
34 import org.openhab.core.types.State;
37 * The {@link HotWaterHandler} is responsible for handling commands, which are
38 * sent to one of the channels.
40 * @author Andrew Schofield - Initial contribution
41 * @author Hilbrand Bouwkamp - Simplified handler to handle null data
44 public class HotWaterHandler extends DraytonWiserThingHandler<HotWaterData> {
46 public HotWaterHandler(final Thing thing) {
51 protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
52 if (command instanceof OnOffType && CHANNEL_MANUAL_MODE_STATE.equals(channelId)) {
53 setManualMode(OnOffType.ON.equals(command));
54 } else if (command instanceof OnOffType && CHANNEL_HOT_WATER_SETPOINT.equals(channelId)) {
55 setSetPoint(OnOffType.ON.equals(command));
56 } else if (command instanceof DecimalType && CHANNEL_HOT_WATER_BOOST_DURATION.equals(channelId)) {
57 setBoostDuration(Math.round((Float.parseFloat(command.toString()) * 60)));
62 protected void refresh() {
63 updateState(CHANNEL_HOT_WATER_OVERRIDE, this::getHotWaterOverride);
64 updateState(CHANNEL_HOTWATER_DEMAND_STATE, this::getHotWaterDemandState);
65 updateState(CHANNEL_MANUAL_MODE_STATE, this::getManualModeState);
66 updateState(CHANNEL_HOT_WATER_SETPOINT, this::getSetPointState);
67 updateState(CHANNEL_HOT_WATER_BOOSTED, this::getBoostedState);
68 updateState(CHANNEL_HOT_WATER_BOOST_REMAINING, this::getBoostRemainingState);
72 protected @Nullable HotWaterData collectData(final DraytonWiserDTO domainDTOProxy) {
73 final SystemDTO system = domainDTOProxy.getSystem();
74 final List<HotWaterDTO> hotWater = domainDTOProxy.getHotWater();
76 return system == null ? null : new HotWaterData(system, hotWater);
79 private State getHotWaterOverride() {
80 return OnOffType.from("ON".equalsIgnoreCase(getData().system.getHotWaterButtonOverrideState()));
83 private State getHotWaterDemandState() {
84 final List<HotWaterDTO> hotWater = getData().hotWater;
85 return OnOffType.from(!hotWater.isEmpty() && "ON".equalsIgnoreCase(hotWater.get(0).getHotWaterRelayState()));
88 private State getManualModeState() {
89 final List<HotWaterDTO> hotWater = getData().hotWater;
90 return OnOffType.from(!hotWater.isEmpty() && "MANUAL".equalsIgnoreCase(hotWater.get(0).getMode()));
93 private State getSetPointState() {
94 final List<HotWaterDTO> hotWater = getData().hotWater;
95 return OnOffType.from(!hotWater.isEmpty() && "ON".equalsIgnoreCase(hotWater.get(0).getWaterHeatingState()));
98 private void setManualMode(final boolean manualMode) throws DraytonWiserApiException {
99 getApi().setHotWaterManualMode(manualMode);
102 private void setSetPoint(final boolean setPointMode) throws DraytonWiserApiException {
103 getApi().setHotWaterSetPoint(setPointMode ? 1100 : -200);
106 private void setBoostDuration(final int durationMinutes) throws DraytonWiserApiException {
107 if (durationMinutes > 0) {
108 getApi().setHotWaterBoostActive(durationMinutes);
110 getApi().setHotWaterBoostInactive();
114 private State getBoostedState() {
115 if (getData().hotWater.size() >= 1) {
116 final HotWaterDTO firstChannel = getData().hotWater.get(0);
118 if (firstChannel.getOverrideTimeoutUnixTime() != null
119 && !"NONE".equalsIgnoreCase(firstChannel.getOverrideType())) {
124 updateState(CHANNEL_HOT_WATER_BOOST_DURATION, DecimalType.ZERO);
126 return OnOffType.OFF;
129 private State getBoostRemainingState() {
130 if (getData().hotWater.size() >= 1) {
131 final HotWaterDTO firstChannel = getData().hotWater.get(0);
132 final Integer overrideTimeout = firstChannel.getOverrideTimeoutUnixTime();
134 if (overrideTimeout != null && !"NONE".equalsIgnoreCase(firstChannel.getOverrideType())) {
135 return new QuantityType<Time>(overrideTimeout - (System.currentTimeMillis() / 1000L), Units.SECOND);
138 return new QuantityType<Time>(0, Units.SECOND);
141 static class HotWaterData {
142 public final SystemDTO system;
143 public final List<HotWaterDTO> hotWater;
145 public HotWaterData(final SystemDTO system, final List<HotWaterDTO> hotWater) {
146 this.system = system;
147 this.hotWater = hotWater;