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;
19 import org.openhab.binding.loxone.internal.types.LxCategory;
20 import org.openhab.binding.loxone.internal.types.LxTags;
21 import org.openhab.binding.loxone.internal.types.LxUuid;
22 import org.openhab.core.library.types.IncreaseDecreaseType;
23 import org.openhab.core.library.types.OnOffType;
24 import org.openhab.core.library.types.PercentType;
25 import org.openhab.core.thing.type.ChannelTypeUID;
26 import org.openhab.core.types.Command;
29 * An EIB dimmer type of control on Loxone Miniserver.
31 * This control is absent in the API documentation. It looks like it behaves like a normal Dimmer, but it is missing the
32 * information about min, max and step values.
34 * @author Pawel Pieczul - initial contribution
37 class LxControlEIBDimmer extends LxControl {
39 static class Factory extends LxControlInstance {
41 LxControl create(LxUuid uuid) {
42 return new LxControlEIBDimmer(uuid);
54 private static final String STATE_POSITION = "position";
55 private static final Double DEFAULT_MIN = 0.0;
56 private static final Double DEFAULT_MAX = 100.0;
57 private static final Double DEFAULT_STEP = 5.0;
60 * Command string used to set the dimmer ON
62 private static final String CMD_ON = "On";
64 * Command string used to set the dimmer to OFF
66 private static final String CMD_OFF = "Off";
68 LxControlEIBDimmer(LxUuid uuid) {
73 public void initialize(LxControlConfig config) {
74 super.initialize(config);
75 LxCategory category = getCategory();
76 if (category != null && category.getType() == LxCategory.CategoryType.LIGHTS) {
77 tags.addAll(LxTags.LIGHTING);
79 addChannel("Dimmer", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_DIMMER), defaultChannelLabel,
80 "Dimmer", tags, this::handleCommands, this::getChannelState);
95 private void handleCommands(Command command) throws IOException {
96 if (command instanceof OnOffType) {
97 if (command == OnOffType.ON) {
102 } else if (command instanceof PercentType) {
103 PercentType percentCmd = (PercentType) command;
104 setPosition(percentCmd.doubleValue());
105 } else if (command instanceof IncreaseDecreaseType) {
106 Double value = getStateDoubleValue(STATE_POSITION);
107 Double min = getMin();
108 Double max = getMax();
109 Double step = getStep();
110 if (value != null && max != null && min != null && step != null && min >= 0 && max >= 0 && max > min) {
111 if ((IncreaseDecreaseType) command == IncreaseDecreaseType.INCREASE) {
122 sendAction(value.toString());
127 private PercentType getChannelState() {
128 Double value = mapLoxoneToOH(getStateDoubleValue(STATE_POSITION));
129 if (value != null && value >= 0 && value <= 100) {
130 return new PercentType(value.intValue());
136 * Sets the current position of the dimmer
138 * @param position position to move to (0-100, 0 - full off, 100 - full on)
139 * @throws IOException error communicating with the Miniserver
141 private void setPosition(Double position) throws IOException {
142 Double loxonePosition = mapOHToLoxone(position);
143 if (loxonePosition != null) {
144 sendAction(loxonePosition.toString());
148 private Double mapLoxoneToOH(Double loxoneValue) {
149 if (loxoneValue != null) {
150 // 0 means turn dimmer off, any value above zero should be mapped from min-max range
151 if (Double.compare(loxoneValue, 0.0) == 0) {
154 Double max = getMax();
155 Double min = getMin();
156 if (max != null && min != null && max > min && min >= 0 && max >= 0) {
157 return 100 * (loxoneValue - min) / (max - min);
163 private Double mapOHToLoxone(Double ohValue) {
164 if (ohValue != null) {
165 // 0 means turn dimmer off, any value above zero should be mapped to min-max range
166 if (Double.compare(ohValue, 0.0) == 0) {
169 Double max = getMax();
170 Double min = getMin();
171 if (max != null && min != null) {
172 double value = min + ohValue * (max - min) / 100;
173 return value; // no rounding to integer value is needed as loxone is accepting floating point values