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 org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.draytonwiser.internal.api.DraytonWiserApiException;
22 import org.openhab.binding.draytonwiser.internal.handler.HotWaterHandler.HotWaterData;
23 import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
24 import org.openhab.binding.draytonwiser.internal.model.HotWaterDTO;
25 import org.openhab.binding.draytonwiser.internal.model.SystemDTO;
26 import org.openhab.core.library.types.DecimalType;
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.Thing;
31 import org.openhab.core.types.Command;
32 import org.openhab.core.types.State;
35 * The {@link HotWaterHandler} is responsible for handling commands, which are
36 * sent to one of the channels.
38 * @author Andrew Schofield - Initial contribution
39 * @author Hilbrand Bouwkamp - Simplified handler to handle null data
42 public class HotWaterHandler extends DraytonWiserThingHandler<HotWaterData> {
44 public HotWaterHandler(final Thing thing) {
49 protected void handleCommand(final String channelId, final Command command) throws DraytonWiserApiException {
50 if (command instanceof OnOffType && CHANNEL_MANUAL_MODE_STATE.equals(channelId)) {
51 setManualMode(OnOffType.ON.equals(command));
52 } else if (command instanceof OnOffType && CHANNEL_HOT_WATER_SETPOINT.equals(channelId)) {
53 setSetPoint(OnOffType.ON.equals(command));
54 } else if (command instanceof DecimalType && CHANNEL_HOT_WATER_BOOST_DURATION.equals(channelId)) {
55 setBoostDuration(Math.round((Float.parseFloat(command.toString()) * 60)));
60 protected void refresh() {
61 updateState(CHANNEL_HOT_WATER_OVERRIDE, this::getHotWaterOverride);
62 updateState(CHANNEL_HOTWATER_DEMAND_STATE, this::getHotWaterDemandState);
63 updateState(CHANNEL_MANUAL_MODE_STATE, this::getManualModeState);
64 updateState(CHANNEL_HOT_WATER_SETPOINT, this::getSetPointState);
65 updateState(CHANNEL_HOT_WATER_BOOSTED, this::getBoostedState);
66 updateState(CHANNEL_HOT_WATER_BOOST_REMAINING, this::getBoostRemainingState);
70 protected @Nullable HotWaterData collectData(final DraytonWiserDTO domainDTOProxy) {
71 final SystemDTO system = domainDTOProxy.getSystem();
72 final List<HotWaterDTO> hotWater = domainDTOProxy.getHotWater();
74 return system == null ? null : new HotWaterData(system, hotWater);
77 private State getHotWaterOverride() {
78 return OnOffType.from("ON".equalsIgnoreCase(getData().system.getHotWaterButtonOverrideState()));
81 private State getHotWaterDemandState() {
82 final List<HotWaterDTO> hotWater = getData().hotWater;
83 return OnOffType.from(!hotWater.isEmpty() && "ON".equalsIgnoreCase(hotWater.get(0).getHotWaterRelayState()));
86 private State getManualModeState() {
87 final List<HotWaterDTO> hotWater = getData().hotWater;
88 return OnOffType.from(!hotWater.isEmpty() && "MANUAL".equalsIgnoreCase(hotWater.get(0).getMode()));
91 private State getSetPointState() {
92 final List<HotWaterDTO> hotWater = getData().hotWater;
93 return OnOffType.from(!hotWater.isEmpty() && "ON".equalsIgnoreCase(hotWater.get(0).getWaterHeatingState()));
96 private void setManualMode(final boolean manualMode) throws DraytonWiserApiException {
97 getApi().setHotWaterManualMode(manualMode);
100 private void setSetPoint(final boolean setPointMode) throws DraytonWiserApiException {
101 getApi().setHotWaterSetPoint(setPointMode ? 1100 : -200);
104 private void setBoostDuration(final int durationMinutes) throws DraytonWiserApiException {
105 if (durationMinutes > 0) {
106 getApi().setHotWaterBoostActive(durationMinutes);
108 getApi().setHotWaterBoostInactive();
112 private State getBoostedState() {
113 if (getData().hotWater.size() >= 1) {
114 final HotWaterDTO firstChannel = getData().hotWater.get(0);
116 if (firstChannel.getOverrideTimeoutUnixTime() != null
117 && !"NONE".equalsIgnoreCase(firstChannel.getOverrideType())) {
122 updateState(CHANNEL_HOT_WATER_BOOST_DURATION, DecimalType.ZERO);
124 return OnOffType.OFF;
127 private State getBoostRemainingState() {
128 if (getData().hotWater.size() >= 1) {
129 final HotWaterDTO firstChannel = getData().hotWater.get(0);
130 final Integer overrideTimeout = firstChannel.getOverrideTimeoutUnixTime();
132 if (overrideTimeout != null && !"NONE".equalsIgnoreCase(firstChannel.getOverrideType())) {
133 return new QuantityType<>(overrideTimeout - (System.currentTimeMillis() / 1000L), Units.SECOND);
136 return new QuantityType<>(0, Units.SECOND);
139 static class HotWaterData {
140 public final SystemDTO system;
141 public final List<HotWaterDTO> hotWater;
143 public HotWaterData(final SystemDTO system, final List<HotWaterDTO> hotWater) {
144 this.system = system;
145 this.hotWater = hotWater;