]> git.basschouten.com Git - openhab-addons.git/blob
56bbee73df2e82f97d52a6902d3e52960ac8e9aa
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.velux.internal.things;
14
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.velux.internal.VeluxBindingConstants;
17 import org.openhab.core.library.types.PercentType;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * <B>Velux</B> product characteristics: Product Position.
23  * <P>
24  * See <a href=
25  * "https://velcdn.azureedge.net/~/media/com/api/klf200/technical%20specification%20for%20klf%20200%20api.pdf#page=110">KLF200
26  * Standard Parameter definition</a>
27  * <P>
28  * Methods in handle this type of information:
29  * <UL>
30  * <LI>{@link #VeluxProductPosition(int)} to convert a Velux value into the characteristic.</LI>
31  * <LI>{@link #VeluxProductPosition(PercentType)} to convert an openHAB value into the characteristic.</LI>
32  * <LI>{@link #VeluxProductPosition()} to convert an openHAB STOP value into the characteristic.</LI>
33  * <LI>{@link #isValid} to determine whether the characteristic has got a valid value.</LI>
34  * <LI>{@link #getPositionAsPercentType()} to convert the characteristic into an openHAB value.</LI>
35  * <LI>{@link #getPositionAsVeluxType()} to convert the characteristic into a Velux value.</LI>
36  * <LI>{@link #toString} to retrieve a human-readable description of this characteristic.</LI>
37  * </UL>
38  *
39  * @see VeluxKLFAPI
40  *
41  * @author Guenther Schreiner - initial contribution.
42  */
43 @NonNullByDefault
44 public class VeluxProductPosition {
45     private final Logger logger = LoggerFactory.getLogger(getClass());
46
47     // Public definition
48
49     public static final VeluxProductPosition UNKNOWN = new VeluxProductPosition();
50     public static final int VPP_VELUX_STOP = 0xD200;
51     public static final int VPP_VELUX_DEFAULT = 0xD300;
52     public static final int VPP_VELUX_IGNORE = 0xD400;
53
54     // Make sure that the calculation are done as non-integer
55     private static final float ONE = 1;
56
57     private static final int VPP_UNKNOWN = 0;
58
59     private static final int VPP_OPENHAB_MIN = 0;
60     private static final int VPP_OPENHAB_MAX = 100;
61
62     public static final int VPP_VELUX_MIN = 0x0000;
63     public static final int VPP_VELUX_MAX = 0xc800;
64     public static final int VPP_VELUX_UNKNOWN = 0xF7FF;
65
66     // relative mode commands
67     private static final int VPP_VELUX_RELATIVE_ORIGIN = 0xCCE8;
68     private static final int VPP_VELUX_RELATIVE_RANGE = 1000; // same for positive and negative offsets
69
70     // Class internal
71
72     private PercentType position;
73     private boolean isValid = false;
74
75     // Constructor
76
77     /**
78      * Creation of a Position object to specify a distinct actuator setting.
79      *
80      * @param position A position as type {@link PercentType} (between 0 and 100).
81      */
82     public VeluxProductPosition(PercentType position) {
83         logger.trace("VeluxProductPosition({} as PercentType) created.", position.intValue());
84         this.position = position;
85         this.isValid = true;
86     }
87
88     /**
89      * Creation of a Position object to specify a distinct actuator setting.
90      *
91      * @param position A position as type {@link PercentType} (between 0 and 100).
92      * @param toBeInverted Flag whether the value should be handled as inverted.
93      */
94     public VeluxProductPosition(PercentType position, boolean toBeInverted) {
95         this(toBeInverted ? new PercentType(PercentType.HUNDRED.intValue() - position.intValue()) : position);
96     }
97
98     /**
99      * Creation of a Position object to specify a distinct actuator setting.
100      *
101      * @param veluxPosition A position as type {@link int} based on the Velux-specific value ranges (between 0x0000 and
102      *            0xc800, or 0xD200 for stop).
103      */
104     public VeluxProductPosition(int veluxPosition) {
105         logger.trace("VeluxProductPosition(constructur with {} as veluxPosition) called.", veluxPosition);
106         if ((veluxPosition == VPP_VELUX_UNKNOWN) || (veluxPosition == VPP_VELUX_STOP) || (veluxPosition < VPP_VELUX_MIN)
107                 || (veluxPosition > VPP_VELUX_MAX)) {
108             logger.trace("VeluxProductPosition() gives up.");
109             this.position = new PercentType(VPP_UNKNOWN);
110             this.isValid = false;
111         } else {
112             float result = (ONE * veluxPosition - VPP_VELUX_MIN) / (VPP_VELUX_MAX - VPP_VELUX_MIN);
113             result = Math.round(VPP_OPENHAB_MIN + result * (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN));
114             logger.trace("VeluxProductPosition() created with percent-type {}.", (int) result);
115             this.position = new PercentType((int) result);
116             this.isValid = true;
117         }
118     }
119
120     /**
121      * Creation of a Position object to specify a STOP.
122      */
123     public VeluxProductPosition() {
124         logger.trace("VeluxProductPosition() as STOP position created.");
125         this.position = new PercentType(VPP_UNKNOWN);
126         this.isValid = false;
127     }
128
129     // Class access methods
130
131     public boolean isValid() {
132         return this.isValid;
133     }
134
135     public PercentType getPositionAsPercentType() {
136         return position;
137     }
138
139     public PercentType getPositionAsPercentType(boolean toBeInverted) {
140         return toBeInverted ? new PercentType(PercentType.HUNDRED.intValue() - position.intValue()) : position;
141     }
142
143     public int getPositionAsVeluxType() {
144         if (this.isValid) {
145             float result = (ONE * position.intValue() - VPP_OPENHAB_MIN) / (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN);
146             result = VPP_VELUX_MIN + result * (VPP_VELUX_MAX - VPP_VELUX_MIN);
147             return (int) result;
148         } else {
149             return VPP_VELUX_STOP;
150         }
151     }
152
153     @Override
154     public String toString() {
155         if (this.isValid) {
156             return String.format("%d", position.intValue());
157         } else {
158             return new String(VeluxBindingConstants.UNKNOWN);
159         }
160     }
161
162     // Helper methods
163
164     public int getAsRelativePosition(boolean positive) {
165         int offset = position.intValue() * VPP_VELUX_RELATIVE_RANGE / (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN);
166         return positive ? VPP_VELUX_RELATIVE_ORIGIN + offset : VPP_VELUX_RELATIVE_ORIGIN - offset;
167     }
168 }