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.warmup.internal.handler;
15 import static org.openhab.binding.warmup.internal.WarmupBindingConstants.*;
17 import java.math.BigDecimal;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.warmup.internal.api.MyWarmupApiException;
22 import org.openhab.binding.warmup.internal.model.query.LocationDTO;
23 import org.openhab.binding.warmup.internal.model.query.QueryResponseDTO;
24 import org.openhab.binding.warmup.internal.model.query.RoomDTO;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.library.types.QuantityType;
27 import org.openhab.core.library.unit.SIUnits;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.types.Command;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * @author James Melville - Initial contribution
40 public class RoomHandler extends WarmupThingHandler implements WarmupRefreshListener {
42 private final Logger logger = LoggerFactory.getLogger(RoomHandler.class);
43 private @Nullable RoomConfigurationDTO config;
45 public RoomHandler(Thing thing) {
50 public void initialize() {
52 config = getConfigAs(RoomConfigurationDTO.class);
53 if (config.getSerialNumber().length() == 0) {
54 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Serial Number not configured");
56 super.refreshFromServer();
61 public void handleCommand(ChannelUID channelUID, Command command) {
62 super.handleCommand(channelUID, command);
63 if (CHANNEL_TARGET_TEMPERATURE.equals(channelUID.getId())
64 && command instanceof QuantityType<?> quantityCommand) {
65 setOverride(quantityCommand);
67 if (CHANNEL_FROST_PROTECTION_MODE.equals(channelUID.getId()) && command instanceof OnOffType onOffCommand) {
68 toggleFrostProtectionMode(onOffCommand);
73 * Process device list and populate room properties, status and state
75 * @param domain Data model representing all devices
78 public void refresh(@Nullable QueryResponseDTO domain) {
80 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "No data from bridge");
81 } else if (config != null) {
82 final String serialNumber = config.getSerialNumber();
83 for (LocationDTO location : domain.getData().getUser().getLocations()) {
84 for (RoomDTO room : location.getRooms()) {
85 if (room.getThermostat4ies() != null && !room.getThermostat4ies().isEmpty()
86 && room.getThermostat4ies().get(0).getDeviceSN().equals(serialNumber)) {
87 if (room.getThermostat4ies().get(0).getLastPoll() > 10) {
88 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
89 "Thermostat has not polled for 10 minutes");
91 updateStatus(ThingStatus.ONLINE);
93 updateProperty(PROPERTY_ROOM_ID, room.getId());
94 updateProperty(PROPERTY_ROOM_NAME, room.getName());
95 updateProperty(PROPERTY_LOCATION_ID, location.getId());
96 updateProperty(PROPERTY_LOCATION_NAME, location.getName());
98 updateState(CHANNEL_CURRENT_TEMPERATURE, parseTemperature(room.getCurrentTemperature()));
99 updateState(CHANNEL_TARGET_TEMPERATURE, parseTemperature(room.getTargetTemperature()));
100 updateState(CHANNEL_OVERRIDE_DURATION, parseDuration(room.getOverrideDuration()));
101 updateState(CHANNEL_RUN_MODE, parseString(room.getRunMode()));
102 updateState(CHANNEL_FROST_PROTECTION_MODE,
103 OnOffType.from(room.getRunMode().equals(FROST_PROTECTION_MODE)));
109 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Room not found");
111 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Room not configured");
115 private void setOverride(final QuantityType<?> command) {
116 String roomId = getThing().getProperties().get(PROPERTY_ROOM_ID);
117 String locationId = getThing().getProperties().get(PROPERTY_LOCATION_ID);
119 QuantityType<?> temp = command.toUnit(SIUnits.CELSIUS);
122 final int value = temp.multiply(BigDecimal.TEN).intValue();
125 final MyWarmupAccountHandler bridgeHandler = getBridgeHandler();
126 if (bridgeHandler != null && config != null) {
127 final int overrideDuration = config.getOverrideDuration();
128 if (overrideDuration > 0 && locationId != null && roomId != null) {
129 bridgeHandler.getApi().setOverride(locationId, roomId, value, overrideDuration);
133 } catch (MyWarmupApiException e) {
134 logger.debug("Set Override failed: {}", e.getMessage());
139 private void toggleFrostProtectionMode(OnOffType command) {
140 String roomId = getThing().getProperties().get(PROPERTY_ROOM_ID);
141 String locationId = getThing().getProperties().get(PROPERTY_LOCATION_ID);
143 final MyWarmupAccountHandler bridgeHandler = getBridgeHandler();
144 if (bridgeHandler != null && locationId != null && roomId != null) {
145 bridgeHandler.getApi().toggleFrostProtectionMode(locationId, roomId, command);
148 } catch (MyWarmupApiException e) {
149 logger.debug("Toggle Frost Protection failed: {}", e.getMessage());