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.math.BigDecimal;
20 import org.openhab.binding.loxone.internal.types.LxUuid;
21 import org.openhab.core.library.types.DecimalType;
22 import org.openhab.core.thing.ChannelUID;
23 import org.openhab.core.thing.type.ChannelTypeUID;
24 import org.openhab.core.types.Command;
25 import org.openhab.core.types.State;
26 import org.openhab.core.types.StateDescriptionFragmentBuilder;
27 import org.openhab.core.types.UnDefType;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
32 * An UpDownAnalog type of control on Loxone Miniserver.
34 * According to Loxone API documentation, UpDownAnalog control is a virtual input that is analog and has an input type
35 * up-down buttons. The analog buttons are simulated as a single analog number value.
37 * @author Pawel Pieczul - initial contribution
40 class LxControlUpDownAnalog extends LxControl {
42 static class Factory extends LxControlInstance {
44 LxControl create(LxUuid uuid) {
45 return new LxControlUpDownAnalog(uuid);
50 return "updownanalog";
54 private static final String STATE_VALUE = "value";
55 private static final String STATE_ERROR = "error";
57 private final Logger logger = LoggerFactory.getLogger(LxControlUpDownAnalog.class);
59 private Double minValue;
60 private Double maxValue;
61 private ChannelUID channelId;
63 LxControlUpDownAnalog(LxUuid uuid) {
68 public void initialize(LxControlConfig config) {
69 initialize(config, "Up/Down Analog");
72 void initialize(LxControlConfig config, String channelDescription) {
73 super.initialize(config);
74 channelId = addChannel("Number", new ChannelTypeUID(BINDING_ID, MINISERVER_CHANNEL_TYPE_NUMBER),
75 defaultChannelLabel, channelDescription, tags, this::handleCommands, this::getChannelState);
76 if (details != null && details.min != null && details.max != null) {
77 if (details.min <= details.max) {
78 minValue = details.min;
79 maxValue = details.max;
80 if (details.step != null) {
81 addChannelStateDescriptionFragment(channelId,
82 StateDescriptionFragmentBuilder.create().withMinimum(new BigDecimal(minValue))
83 .withMaximum(new BigDecimal(maxValue)).withStep(new BigDecimal(details.step))
84 .withPattern(details.format != null ? details.format : "%.1f").withReadOnly(false)
88 logger.warn("Received min value > max value: {}, {}", minValue, maxValue);
93 private void handleCommands(Command command) throws IOException {
94 if (command instanceof DecimalType) {
95 Double value = ((DecimalType) command).doubleValue();
96 if (minValue != null && maxValue != null && value >= minValue && value <= maxValue) {
97 sendAction(value.toString());
99 // we'll update the state value to reflect current real value that has not been changed
100 setChannelState(channelId, getChannelState());
105 private State getChannelState() {
106 Double error = getStateDoubleValue(STATE_ERROR);
107 if (error == null || error == 0.0) {
108 Double value = getStateDoubleValue(STATE_VALUE);
110 if (minValue != null && maxValue != null && (minValue > value || maxValue < value)) {
113 return new DecimalType(value);
116 return UnDefType.UNDEF;