2 * Copyright (c) 2010-2023 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.loxone.internal.controls;
15 import static org.openhab.binding.loxone.internal.LxBindingConstants.*;
17 import java.io.IOException;
18 import java.util.HashSet;
21 import org.openhab.binding.loxone.internal.types.LxTags;
22 import org.openhab.binding.loxone.internal.types.LxUuid;
23 import org.openhab.core.library.types.DecimalType;
24 import org.openhab.core.thing.ChannelUID;
25 import org.openhab.core.thing.type.ChannelTypeUID;
26 import org.openhab.core.types.Command;
27 import org.openhab.core.types.State;
28 import org.openhab.core.types.StateDescriptionFragment;
29 import org.openhab.core.types.StateDescriptionFragmentBuilder;
32 * An Intelligent Room Controller V2.
33 * This implementation does not support the timers which describe temperature zones during the day.
35 * @author Pawel Pieczul - initial contribution
38 class LxControlIRoomControllerV2 extends LxControl {
40 static class Factory extends LxControlInstance {
42 LxControl create(LxUuid uuid) {
43 return new LxControlIRoomControllerV2(uuid);
48 return "iroomcontrollerv2";
52 private static final String STATE_ACTIVE_MODE = "activemode";
53 private static final String STATE_OPERATING_MODE = "operatingmode";
54 private static final String STATE_PREPARE_STATE = "preparestate";
55 private static final String STATE_OPEN_WINDOW = "openwindow";
56 private static final String STATE_TEMP_ACTUAL = "tempactual";
57 private static final String STATE_TEMP_TARGET = "temptarget";
58 private static final String STATE_COMFORT_TEMPERATURE = "comforttemperature";
59 private static final String STATE_COMFORT_TEMPERATURE_OFFSET = "comforttemperatureoffset";
60 private static final String STATE_COMFORT_TOLERANCE = "comforttolerance";
61 private static final String STATE_ABSENT_MIN_OFFSET = "absentminoffset";
62 private static final String STATE_ABSENT_MAX_OFFSET = "absentmaxoffset";
63 private static final String STATE_FROST_PROTECT_TEMPERATURE = "frostprotecttemperature";
64 private static final String STATE_HEAT_PROTECT_TEMPERATURE = "heatprotecttemperature";
66 private static final String CMD_SET_OPERATING_MODE = "setOperatingMode/";
67 private static final String CMD_SET_COMFORT_TOLERANCE = "setComfortTolerance/";
68 private static final String CMD_SET_COMFORT_TEMPERATURE = "setComfortTemperature/";
69 private static final String CMD_SET_COMFORT_TEMPERATURE_OFFSET = "setComfortModeTemp/";
70 private static final String CMD_SET_ABSENT_MIN_TEMPERATURE = "setAbsentMinTemperature/";
71 private static final String CMD_SET_ABSENT_MAX_TEMPERATURE = "setAbsentMaxTemperature/";
72 private static final String CMD_SET_MANUAL_TEMPERATURE = "setManualTemperature/";
74 private LxControlIRoomControllerV2(LxUuid uuid) {
79 public void initialize(LxControlConfig config) {
80 super.initialize(config);
82 Set<String> tempTags = new HashSet<>(tags);
83 tempTags.addAll(LxTags.TEMPERATURE);
84 String format = details.format;
85 StateDescriptionFragment patternRoFragment = null;
86 StateDescriptionFragment patternRwFragment = null;
88 patternRoFragment = StateDescriptionFragmentBuilder.create().withPattern(format).withReadOnly(true).build();
89 patternRwFragment = StateDescriptionFragmentBuilder.create().withPattern(format).withReadOnly(false)
93 addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_IROOM_V2_ACTIVE_MODE),
94 defaultChannelLabel + "/ Active Mode", "Active mode", tags, null,
95 () -> getStateDecimalValue(STATE_ACTIVE_MODE));
97 addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_IROOM_V2_OPERATING_MODE),
98 defaultChannelLabel + "/ Operating Mode", "Operating mode", tags, this::setOperatingMode,
99 () -> getStateDecimalValue(STATE_OPERATING_MODE));
101 addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_IROOM_V2_PREPARE_STATE),
102 defaultChannelLabel + "/ Prepare State", "Prepare state", tags, null,
103 () -> getStateDecimalValue(STATE_PREPARE_STATE));
105 addChannel("Switch", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_RO_SWITCH),
106 defaultChannelLabel + "/ Open Window", "Open window", tags, null,
107 () -> getSwitchState(STATE_OPEN_WINDOW));
109 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_RO_ANALOG),
110 defaultChannelLabel + "/ Current Temperature", "Current temperature", tempTags, null,
111 () -> getStateDecimalValue(STATE_TEMP_ACTUAL));
112 addChannelStateDescriptionFragment(cid, patternRoFragment);
114 // manual temperature will affect value of target temperature only in manual operating modes
115 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_NUMBER),
116 defaultChannelLabel + "/ Target Temperature", "Target temperature", tempTags,
117 (c) -> setTemperature(c, CMD_SET_MANUAL_TEMPERATURE), () -> getStateDecimalValue(STATE_TEMP_TARGET));
118 addChannelStateDescriptionFragment(cid, patternRwFragment);
120 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_NUMBER),
121 defaultChannelLabel + "/ Comfort Temperature", "Comfort temperature", tempTags,
122 (c) -> setTemperature(c, CMD_SET_COMFORT_TEMPERATURE),
123 () -> getStateDecimalValue(STATE_COMFORT_TEMPERATURE));
124 addChannelStateDescriptionFragment(cid, patternRwFragment);
126 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_NUMBER),
127 defaultChannelLabel + "/ Comfort Temperature Offset", "Comfort temperature offset", tempTags,
128 (c) -> setTemperature(c, CMD_SET_COMFORT_TEMPERATURE_OFFSET),
129 () -> getStateDecimalValue(STATE_COMFORT_TEMPERATURE_OFFSET));
130 addChannelStateDescriptionFragment(cid, patternRwFragment);
132 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_IROOM_V2_COMFORT_TOLERANCE),
133 defaultChannelLabel + "/ Comfort Tolerance", "Comfort tolerance", tempTags,
134 (c) -> setTemperature(c, CMD_SET_COMFORT_TOLERANCE),
135 () -> getStateDecimalValue(STATE_COMFORT_TOLERANCE));
136 addChannelStateDescriptionFragment(cid, patternRwFragment);
138 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_NUMBER),
139 defaultChannelLabel + "/ Absent Min Offset", "Absent minimum temperature offset", tempTags,
140 (c) -> setTemperature(c, CMD_SET_ABSENT_MIN_TEMPERATURE),
141 () -> getStateDecimalValue(STATE_ABSENT_MIN_OFFSET));
142 addChannelStateDescriptionFragment(cid, patternRwFragment);
144 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_NUMBER),
145 defaultChannelLabel + "/ Absent Max Offset", "Absent maximum temperature offset", tempTags,
146 (c) -> setTemperature(c, CMD_SET_ABSENT_MAX_TEMPERATURE),
147 () -> getStateDecimalValue(STATE_ABSENT_MAX_OFFSET));
148 addChannelStateDescriptionFragment(cid, patternRwFragment);
150 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_RO_ANALOG),
151 defaultChannelLabel + "/ Frost Protect Temperature", "Frost protect temperature", tempTags, null,
152 () -> getStateDecimalValue(STATE_FROST_PROTECT_TEMPERATURE));
153 addChannelStateDescriptionFragment(cid, patternRoFragment);
155 cid = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_RO_ANALOG),
156 defaultChannelLabel + "/ Heat Protect Temperature", "Heat protect temperature", tempTags, null,
157 () -> getStateDecimalValue(STATE_HEAT_PROTECT_TEMPERATURE));
158 addChannelStateDescriptionFragment(cid, patternRoFragment);
161 private State getSwitchState(String name) {
162 return LxControlSwitch.convertSwitchState(getStateDoubleValue(name));
165 private void setOperatingMode(Command command) throws IOException {
166 if (command instanceof DecimalType mode) {
167 sendAction(CMD_SET_OPERATING_MODE + mode.intValue());
171 private void setTemperature(Command command, String prefix) throws IOException {
172 if (command instanceof DecimalType temp) {
173 sendAction(prefix + temp.doubleValue());