]> git.basschouten.com Git - openhab-addons.git/blob
f1f34e82867c9deafe99879270242ee13805160d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.mqtt.generic.values;
14
15 import java.util.List;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.core.library.CoreItemFactory;
20 import org.openhab.core.library.types.PercentType;
21 import org.openhab.core.library.types.StopMoveType;
22 import org.openhab.core.library.types.StringType;
23 import org.openhab.core.library.types.UpDownType;
24 import org.openhab.core.types.Command;
25
26 /**
27  * Implements a rollershutter value.
28  * <p>
29  * The stop, up and down strings have multiple purposes.
30  * For one if those strings are received via MQTT they are recognised as corresponding commands
31  * and also posted as Commands to the framework.
32  * And if a user commands an Item->Channel to perform Stop the corresponding string is send. For Up,Down
33  * the percentage 0 and 100 is send.
34  *
35  * @author David Graeff - Initial contribution
36  */
37 @NonNullByDefault
38 public class RollershutterValue extends Value {
39     // openHAB interprets open rollershutters as 0, and closed as 100
40     private static final String UP_VALUE = "0";
41     private static final String DOWN_VALUE = "100";
42     // other devices may interpret it the opposite, so we need to be able
43     // to invert it
44     private static final String INVERTED_UP_VALUE = DOWN_VALUE;
45     private static final String INVERTED_DOWN_VALUE = UP_VALUE;
46
47     private final @Nullable String upCommandString;
48     private final @Nullable String downCommandString;
49     private final @Nullable String stopCommandString;
50     private final @Nullable String upStateString;
51     private final @Nullable String downStateString;
52     private final boolean inverted;
53     private final boolean transformExtentsToString;
54
55     /**
56      * Creates a new rollershutter value.
57      *
58      * @param upCommandString The UP command string.
59      * @param downCommandString The DOWN command string.
60      * @param stopCommandString The STOP command string.
61      * @param upStateString The UP value string. This will be compared to MQTT messages.
62      * @param downStateString The DOWN value string. This will be compared to MQTT messages.
63      * @param inverted Whether to invert 0-100/100-0
64      * @param transformExtentsToString Whether 0/100 will be sent as UP/DOWN
65      */
66     public RollershutterValue(@Nullable String upCommandString, @Nullable String downCommandString,
67             @Nullable String stopCommandString, @Nullable String upStateString, @Nullable String downStateString,
68             boolean inverted, boolean transformExtentsToString) {
69         super(CoreItemFactory.ROLLERSHUTTER,
70                 List.of(UpDownType.class, StopMoveType.class, PercentType.class, StringType.class));
71         this.upCommandString = upCommandString;
72         this.downCommandString = downCommandString;
73         this.stopCommandString = stopCommandString;
74         if (upStateString == null) {
75             this.upStateString = upCommandString;
76         } else {
77             this.upStateString = upStateString;
78         }
79         if (downStateString == null) {
80             this.downStateString = downCommandString;
81         } else {
82             this.downStateString = downStateString;
83         }
84         this.inverted = inverted;
85         this.transformExtentsToString = transformExtentsToString;
86     }
87
88     /**
89      * Creates a new rollershutter value.
90      *
91      * @param upString The UP value string. This will be compared to MQTT messages.
92      * @param downString The DOWN value string. This will be compared to MQTT messages.
93      * @param stopString The STOP value string. This will be compared to MQTT messages.
94      */
95     public RollershutterValue(@Nullable String upString, @Nullable String downString, @Nullable String stopString) {
96         this(upString, downString, stopString, upString, downString, false, true);
97     }
98
99     private Command parseType(Command command, @Nullable String upString, @Nullable String downString)
100             throws IllegalArgumentException {
101         if (command instanceof StopMoveType) {
102             if (command == StopMoveType.STOP && stopCommandString != null) {
103                 return command;
104             } else {
105                 throw new IllegalArgumentException(command.toString() + " is not a valid command for MQTT.");
106             }
107         } else if (command instanceof UpDownType) {
108             if (command == UpDownType.UP) {
109                 if (upString != null) {
110                     return command;
111                 } else {
112                     // Do not handle inversion here. See parseCommand below
113                     return PercentType.ZERO;
114                 }
115             } else {
116                 if (downString != null) {
117                     return command;
118                 } else {
119                     // Do not handle inversion here. See parseCommand below
120                     return PercentType.HUNDRED;
121                 }
122             }
123         } else if (command instanceof PercentType percentage) {
124             return percentage;
125         } else if (command instanceof StringType) {
126             final String updatedValue = command.toString();
127             if (updatedValue.equals(upString)) {
128                 return UpDownType.UP;
129             } else if (updatedValue.equals(downString)) {
130                 return UpDownType.DOWN;
131             } else if (updatedValue.equals(stopCommandString)) {
132                 return StopMoveType.STOP;
133             } else {
134                 return PercentType.valueOf(updatedValue);
135             }
136         }
137         throw new IllegalStateException("Cannot call parseCommand() with " + command.toString());
138     }
139
140     @Override
141     public Command parseCommand(Command command) throws IllegalArgumentException {
142         // Do not handle inversion in this code path. parseCommand might be called
143         // multiple times when sending a command TO an MQTT topic. The inversion is
144         // handled _only_ in getMQTTpublishValue
145         return parseType(command, upCommandString, downCommandString);
146     }
147
148     @Override
149     public Command parseMessage(Command command) throws IllegalArgumentException {
150         command = parseType(command, upStateString, downStateString);
151         if (inverted && command instanceof PercentType percentType) {
152             return new PercentType(100 - percentType.intValue());
153         }
154         return command;
155     }
156
157     @Override
158     public String getMQTTpublishValue(Command command, @Nullable String pattern) {
159         return getMQTTpublishValue(command, transformExtentsToString);
160     }
161
162     public String getMQTTpublishValue(Command command, boolean transformExtentsToString) {
163         final String upCommandString = this.upCommandString;
164         final String downCommandString = this.downCommandString;
165         final String stopCommandString = this.stopCommandString;
166         if (command == UpDownType.UP) {
167             if (upCommandString != null) {
168                 return upCommandString;
169             } else {
170                 return (inverted ? INVERTED_UP_VALUE : UP_VALUE);
171             }
172         } else if (command == UpDownType.DOWN) {
173             if (downCommandString != null) {
174                 return downCommandString;
175             } else {
176                 return (inverted ? INVERTED_DOWN_VALUE : DOWN_VALUE);
177             }
178         } else if (command == StopMoveType.STOP) {
179             if (stopCommandString != null) {
180                 return stopCommandString;
181             } else {
182                 return ((StopMoveType) command).name();
183             }
184         } else if (command instanceof PercentType percentage) {
185             if (transformExtentsToString && command.equals(PercentType.HUNDRED) && downCommandString != null) {
186                 return downCommandString;
187             } else if (transformExtentsToString && command.equals(PercentType.ZERO) && upCommandString != null) {
188                 return upCommandString;
189             } else {
190                 int value = percentage.intValue();
191                 if (inverted) {
192                     value = 100 - value;
193                 }
194                 return String.valueOf(value);
195             }
196         } else {
197             throw new IllegalArgumentException("Invalid command type for Rollershutter item");
198         }
199     }
200 }