]> git.basschouten.com Git - openhab-addons.git/blob
af2f45c9b9fdb893b300069336cd1c50c6234499
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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     private static final int VPP_VELUX_MIN = 0x0000;
62     private static final int VPP_VELUX_MAX = 0xc800;
63     private static final int VPP_VELUX_UNKNOWN = 0xF7FF;
64
65     private static final int VPP_VELUX_PERCENTAGE_MIN = 0xc900;
66     private static final int VPP_VELUX_PERCENTAGE_MAX = 0xd0d0;
67
68     // Class internal
69
70     private PercentType position;
71     private boolean isValid = false;
72
73     // Constructor
74
75     /**
76      * Creation of a Position object to specify a distinct actuator setting.
77      *
78      * @param position A position as type {@link PercentType} (between 0 and 100).
79      */
80     public VeluxProductPosition(PercentType position) {
81         logger.trace("VeluxProductPosition({} as PercentType) created.", position.intValue());
82         this.position = position;
83         this.isValid = true;
84     }
85
86     /**
87      * Creation of a Position object to specify a distinct actuator setting.
88      *
89      * @param position A position as type {@link PercentType} (between 0 and 100).
90      * @param toBeInverted Flag whether the value should be handled as inverted.
91      */
92     public VeluxProductPosition(PercentType position, boolean toBeInverted) {
93         this(toBeInverted ? new PercentType(PercentType.HUNDRED.intValue() - position.intValue()) : position);
94     }
95
96     /**
97      * Creation of a Position object to specify a distinct actuator setting.
98      *
99      * @param veluxPosition A position as type {@link int} based on the Velux-specific value ranges (between 0x0000 and
100      *            0xc800, or 0xD200 for stop).
101      */
102     public VeluxProductPosition(int veluxPosition) {
103         logger.trace("VeluxProductPosition(constructur with {} as veluxPosition) called.", veluxPosition);
104         if ((veluxPosition == VPP_VELUX_UNKNOWN) || (veluxPosition == VPP_VELUX_STOP) || (veluxPosition < VPP_VELUX_MIN)
105                 || (veluxPosition > VPP_VELUX_MAX)) {
106             logger.trace("VeluxProductPosition() gives up.");
107             this.position = new PercentType(VPP_UNKNOWN);
108             this.isValid = false;
109         } else {
110             float result = (ONE * veluxPosition - VPP_VELUX_MIN) / (VPP_VELUX_MAX - VPP_VELUX_MIN);
111             result = Math.round(VPP_OPENHAB_MIN + result * (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN));
112             logger.trace("VeluxProductPosition() created with percent-type {}.", (int) result);
113             this.position = new PercentType((int) result);
114             this.isValid = true;
115         }
116     }
117
118     /**
119      * Creation of a Position object to specify a STOP.
120      */
121     public VeluxProductPosition() {
122         logger.trace("VeluxProductPosition() as STOP position created.");
123         this.position = new PercentType(VPP_UNKNOWN);
124         this.isValid = false;
125     }
126
127     // Class access methods
128
129     public boolean isValid() {
130         return this.isValid;
131     }
132
133     public PercentType getPositionAsPercentType() {
134         return position;
135     }
136
137     public PercentType getPositionAsPercentType(boolean toBeInverted) {
138         return toBeInverted ? new PercentType(PercentType.HUNDRED.intValue() - position.intValue()) : position;
139     }
140
141     public int getPositionAsVeluxType() {
142         if (this.isValid) {
143             float result = (ONE * position.intValue() - VPP_OPENHAB_MIN) / (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN);
144             result = VPP_VELUX_MIN + result * (VPP_VELUX_MAX - VPP_VELUX_MIN);
145             return (int) result;
146         } else {
147             return VPP_VELUX_STOP;
148         }
149     }
150
151     @Override
152     public String toString() {
153         if (this.isValid) {
154             return String.format("%d", position.intValue());
155         } else {
156             return new String(VeluxBindingConstants.UNKNOWN);
157         }
158     }
159
160     // Helper methods
161
162     public static int getRelativePositionAsVeluxType(boolean upwards, PercentType position) {
163         float result = (VPP_VELUX_PERCENTAGE_MAX + VPP_VELUX_PERCENTAGE_MIN) / 2;
164         if (upwards) {
165             result = result + (ONE * position.intValue() - VPP_OPENHAB_MIN) / (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN)
166                     * ((VPP_VELUX_PERCENTAGE_MAX - VPP_VELUX_PERCENTAGE_MIN) / 2);
167         } else {
168             result = result - (ONE * position.intValue() - VPP_OPENHAB_MIN) / (VPP_OPENHAB_MAX - VPP_OPENHAB_MIN)
169                     * ((VPP_VELUX_PERCENTAGE_MAX - VPP_VELUX_PERCENTAGE_MIN) / 2);
170         }
171         return (int) result;
172     }
173 }