2 * Copyright (c) 2010-2022 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.velux.internal.bridge.slip;
15 import java.util.Arrays;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.velux.internal.bridge.slip.utils.Packet;
20 import org.openhab.binding.velux.internal.things.VeluxProductPosition;
23 * Implementation of API Functional Parameters.
24 * Supports an array of of four Functional Parameter values { FP1 .. FP4 }
26 * @author Andrew Fiddian-Green - Initial contribution.
30 public class FunctionalParameters {
31 private static final int FUNCTIONAL_PARAMETER_COUNT = 4;
33 private final int[] values;
36 * Private constructor to create a FunctionalParameters instance with all empty values.
38 private FunctionalParameters() {
39 values = new int[FUNCTIONAL_PARAMETER_COUNT];
40 Arrays.fill(values, VeluxProductPosition.VPP_VELUX_UNKNOWN);
44 * Public constructor to create a FunctionalParameters instance from one specific value at one specific index.
46 public FunctionalParameters(int index, int newValue) {
48 values[index] = newValue;
52 public FunctionalParameters clone() {
53 FunctionalParameters result = new FunctionalParameters();
54 System.arraycopy(values, 0, result.values, 0, FUNCTIONAL_PARAMETER_COUNT);
59 public String toString() {
60 return String.format("{0x%04X, 0x%04X, 0x%04X, 0x%04X}", values[0], values[1], values[2], values[3]);
64 * Return the functional parameter value at index.
66 * @return the value at the index.
68 public int getValue(int index) {
73 * Create a Functional Parameters instance from the merger of the data in 'foundationFunctionalParameters' and
74 * 'substituteFunctionalParameters'. Invalid parameter values are not merged. If either
75 * 'foundationFunctionalParameters' or 'substituteFunctionalParameters' is null, the merge includes only the data
76 * from the non null parameter set. And if both sets of parameters are null then the result is also null.
78 * @param foundationFunctionalParameters the Functional Parameters to be used as the foundation for the merge.
79 * @param substituteFunctionalParameters the Functional Parameters to substituted on top (if they can be).
80 * @return a new Functional Parameters class instance containing the merged data.
82 public static @Nullable FunctionalParameters createMergeSubstitute(
83 @Nullable FunctionalParameters foundationFunctionalParameters,
84 @Nullable FunctionalParameters substituteFunctionalParameters) {
85 if (foundationFunctionalParameters == null && substituteFunctionalParameters == null) {
88 FunctionalParameters result = new FunctionalParameters();
89 if (foundationFunctionalParameters != null) {
90 for (int i = 0; i < FUNCTIONAL_PARAMETER_COUNT; i++) {
91 if (isNormalPosition(foundationFunctionalParameters.values[i])) {
92 result.values[i] = foundationFunctionalParameters.values[i];
96 if (substituteFunctionalParameters != null) {
97 for (int i = 0; i < FUNCTIONAL_PARAMETER_COUNT; i++) {
98 if (isNormalPosition(substituteFunctionalParameters.values[i])) {
99 result.values[i] = substituteFunctionalParameters.values[i];
107 * Check if a given parameter value is a normal actuator position value (i.e. 0x0000 .. 0xC800).
109 * @param paramValue the value to be checked.
110 * @return true if it is a normal actuator position value.
112 public static boolean isNormalPosition(int paramValue) {
113 return (paramValue >= VeluxProductPosition.VPP_VELUX_MIN) && (paramValue <= VeluxProductPosition.VPP_VELUX_MAX);
117 * Create a FunctionalParameters instance from the given Packet. Where the parameters are packed into an array of
118 * two byte integer values.
120 * @param responseData the Packet to read from.
121 * @param startPosition the read starting position.
122 * @return this object.
124 public static @Nullable FunctionalParameters readArray(Packet responseData, int startPosition) {
125 int pos = startPosition;
126 boolean isValid = false;
127 FunctionalParameters result = new FunctionalParameters();
128 for (int i = 0; i < FUNCTIONAL_PARAMETER_COUNT; i++) {
129 int value = responseData.getTwoByteValue(pos);
130 if (isNormalPosition(value)) {
131 result.values[i] = value;
136 return isValid ? result : null;
140 * Create a FunctionalParameters instance from the given Packet. Where the parameters are packed into an array of
141 * three byte records each comprising a one byte index followed by a two byte integer value.
143 * @param responseData the Packet to read from.
144 * @param startPosition the read starting position.
145 * @return this object.
147 public static @Nullable FunctionalParameters readArrayIndexed(Packet responseData, int startPosition) {
148 int pos = startPosition;
149 boolean isValid = false;
150 FunctionalParameters result = new FunctionalParameters();
151 for (int i = 0; i < FUNCTIONAL_PARAMETER_COUNT; i++) {
152 int index = responseData.getOneByteValue(pos) - 1;
154 if ((index >= 0) && (index < FUNCTIONAL_PARAMETER_COUNT)) {
155 int value = responseData.getTwoByteValue(pos);
156 if (isNormalPosition(value)) {
157 result.values[index] = value;
163 return isValid ? result : null;
167 * Write the Functional Parameters to the given packet. Only writes normal valid position values.
169 * @param requestData the Packet to write to.
170 * @param startPosition the write starting position.
171 * @return fpIndex a bit map that indicates which of the written Functional Parameters contains a normal valid
174 public int writeArray(Packet requestData, int startPosition) {
175 int bitMask = 0b10000000;
176 int pos = startPosition;
178 for (int i = 0; i < FUNCTIONAL_PARAMETER_COUNT; i++) {
179 if (isNormalPosition(values[i])) {
181 requestData.setTwoByteValue(pos, values[i]);
184 bitMask = bitMask >>> 1;
190 public boolean equals(@Nullable Object obj) {
191 if (!(obj instanceof FunctionalParameters)) {
194 FunctionalParameters other = (FunctionalParameters) obj;
195 for (int i = 0; i < FUNCTIONAL_PARAMETER_COUNT; i++) {
196 if (values[i] != other.values[i]) {
204 public int hashCode() {
205 return Arrays.hashCode(values);