]> git.basschouten.com Git - openhab-addons.git/blob
fbd2ba64ddbbe0697ebab5bf6d6c3e9747c5daaa
[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         this.upStateString = upStateString;
75         this.downStateString = downStateString;
76         this.inverted = inverted;
77         this.transformExtentsToString = transformExtentsToString;
78     }
79
80     /**
81      * Creates a new rollershutter value.
82      *
83      * @param upString The UP value string. This will be compared to MQTT messages.
84      * @param downString The DOWN value string. This will be compared to MQTT messages.
85      * @param stopString The STOP value string. This will be compared to MQTT messages.
86      */
87     public RollershutterValue(@Nullable String upString, @Nullable String downString, @Nullable String stopString) {
88         this(upString, downString, stopString, upString, downString, false, true);
89     }
90
91     private Command parseType(Command command, @Nullable String upString, @Nullable String downString)
92             throws IllegalArgumentException {
93         if (command instanceof StopMoveType) {
94             if (command == StopMoveType.STOP && stopCommandString != null) {
95                 return command;
96             } else {
97                 throw new IllegalArgumentException(command.toString() + " is not a valid command for MQTT.");
98             }
99         } else if (command instanceof UpDownType) {
100             if (command == UpDownType.UP) {
101                 if (upString != null) {
102                     return command;
103                 } else {
104                     // Do not handle inversion here. See parseCommand below
105                     return PercentType.ZERO;
106                 }
107             } else {
108                 if (downString != null) {
109                     return command;
110                 } else {
111                     // Do not handle inversion here. See parseCommand below
112                     return PercentType.HUNDRED;
113                 }
114             }
115         } else if (command instanceof PercentType percentage) {
116             return percentage;
117         } else if (command instanceof StringType) {
118             final String updatedValue = command.toString();
119             if (updatedValue.equals(upString)) {
120                 return UpDownType.UP;
121             } else if (updatedValue.equals(downString)) {
122                 return UpDownType.DOWN;
123             } else if (updatedValue.equals(stopCommandString)) {
124                 return StopMoveType.STOP;
125             } else {
126                 return PercentType.valueOf(updatedValue);
127             }
128         }
129         throw new IllegalStateException("Cannot call parseCommand() with " + command.toString());
130     }
131
132     @Override
133     public Command parseCommand(Command command) throws IllegalArgumentException {
134         // Do not handle inversion in this code path. parseCommand might be called
135         // multiple times when sending a command TO an MQTT topic. The inversion is
136         // handled _only_ in getMQTTpublishValue
137         return parseType(command, upCommandString, downCommandString);
138     }
139
140     @Override
141     public Command parseMessage(Command command) throws IllegalArgumentException {
142         command = parseType(command, upStateString, downStateString);
143         if (inverted && command instanceof PercentType percentType) {
144             return new PercentType(100 - percentType.intValue());
145         }
146         return command;
147     }
148
149     @Override
150     public String getMQTTpublishValue(Command command, @Nullable String pattern) {
151         return getMQTTpublishValue(command, transformExtentsToString);
152     }
153
154     public String getMQTTpublishValue(Command command, boolean transformExtentsToString) {
155         final String upCommandString = this.upCommandString;
156         final String downCommandString = this.downCommandString;
157         final String stopCommandString = this.stopCommandString;
158         if (command == UpDownType.UP) {
159             if (upCommandString != null) {
160                 return upCommandString;
161             } else {
162                 return (inverted ? INVERTED_UP_VALUE : UP_VALUE);
163             }
164         } else if (command == UpDownType.DOWN) {
165             if (downCommandString != null) {
166                 return downCommandString;
167             } else {
168                 return (inverted ? INVERTED_DOWN_VALUE : DOWN_VALUE);
169             }
170         } else if (command == StopMoveType.STOP) {
171             if (stopCommandString != null) {
172                 return stopCommandString;
173             } else {
174                 return ((StopMoveType) command).name();
175             }
176         } else if (command instanceof PercentType percentage) {
177             if (transformExtentsToString && command.equals(PercentType.HUNDRED) && downCommandString != null) {
178                 return downCommandString;
179             } else if (transformExtentsToString && command.equals(PercentType.ZERO) && upCommandString != null) {
180                 return upCommandString;
181             } else {
182                 int value = percentage.intValue();
183                 if (inverted) {
184                     value = 100 - value;
185                 }
186                 return String.valueOf(value);
187             }
188         } else {
189             throw new IllegalArgumentException("Invalid command type for Rollershutter item");
190         }
191     }
192 }