2 * Copyright (c) 2010-2023 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.Random;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.openhab.binding.velux.internal.bridge.common.GetProductLimitation;
19 import org.openhab.binding.velux.internal.bridge.slip.utils.KLF200Response;
20 import org.openhab.binding.velux.internal.bridge.slip.utils.Packet;
21 import org.openhab.binding.velux.internal.things.VeluxKLFAPI.Command;
22 import org.openhab.binding.velux.internal.things.VeluxKLFAPI.CommandNumber;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * Protocol specific bridge communication supported by the Velux bridge:
28 * <B>Retrieve Product Limitations</B>
30 * Common Message semantic: Communication with the bridge and (optionally) storing returned information within the class
33 * As 3rd level class it defines informations how to send query and receive answer through the
34 * {@link org.openhab.binding.velux.internal.bridge.VeluxBridgeProvider VeluxBridgeProvider}
35 * as described by the interface {@link SlipBridgeCommunicationProtocol}.
37 * Methods in addition to the mentioned interface:
39 * <LI>{@link #setActuatorIdAndLimitationType(int,boolean)} to define the one specific product.</LI>
42 * @see GetProductLimitation
43 * @see SlipBridgeCommunicationProtocol
45 * @author Guenther Schreiner - Initial contribution.
48 class SCgetLimitation extends GetProductLimitation implements SlipBridgeCommunicationProtocol {
49 private final Logger logger = LoggerFactory.getLogger(SCgetLimitation.class);
51 private static final String DESCRIPTION = "Retrieve Actuator Limitation";
52 private static final Command COMMAND = Command.GW_GET_LIMITATION_STATUS_REQ;
55 * ===========================================================
56 * Message Content Parameters
59 private int reqSessionID = 0;
60 private int reqIndexArrayCount = 1; // One node will be addressed
61 private int reqIndexArray01 = 1; // This is the node
62 private int reqParameterID = 0; // MP = Main parameter
63 private int reqLimitationType = 0; // Resulting minimum limitation. 1= maximum.
66 * ===========================================================
70 private byte[] requestData = new byte[0];
73 * ===========================================================
77 private boolean success = false;
78 private boolean finished = false;
80 private int limitationValue = 0;
83 * ===========================================================
87 public SCgetLimitation() {
88 logger.debug("SCgetLimitation(Constructor) called.");
89 Random rand = new Random();
90 reqSessionID = rand.nextInt(0x0fff);
91 logger.debug("SCgetLimitation(): starting sessions with the random number {}.", reqSessionID);
95 * ===========================================================
96 * Methods required for interface {@link BridgeCommunicationProtocol}.
100 public String name() {
105 public CommandNumber getRequestCommand() {
108 logger.debug("getRequestCommand() returns {} ({}).", COMMAND.name(), COMMAND.getCommand());
109 return COMMAND.getCommand();
113 public byte[] getRequestDataAsArrayOfBytes() {
114 Packet request = new Packet(new byte[25]);
115 reqSessionID = (reqSessionID + 1) & 0xffff;
116 request.setTwoByteValue(0, reqSessionID);
117 request.setOneByteValue(2, reqIndexArrayCount);
118 request.setOneByteValue(3, reqIndexArray01);
119 request.setOneByteValue(23, reqParameterID);
120 request.setOneByteValue(24, reqLimitationType);
121 logger.trace("getRequestDataAsArrayOfBytes(): ntfSessionID={}.", reqSessionID);
122 logger.trace("getRequestDataAsArrayOfBytes(): reqIndexArrayCount={}.", reqIndexArrayCount);
123 logger.trace("getRequestDataAsArrayOfBytes(): reqIndexArray01={}.", reqIndexArray01);
124 logger.trace("getRequestDataAsArrayOfBytes(): reqParameterID={}.", reqParameterID);
125 logger.trace("getRequestDataAsArrayOfBytes(): reqLimitationType={}.", reqLimitationType);
126 requestData = request.toByteArray();
127 logger.trace("getRequestDataAsArrayOfBytes() data is {}.", new Packet(requestData).toString());
132 public void setResponse(short responseCommand, byte[] thisResponseData, boolean isSequentialEnforced) {
133 KLF200Response.introLogging(logger, responseCommand, thisResponseData);
136 Packet responseData = new Packet(thisResponseData);
137 switch (Command.get(responseCommand)) {
138 case GW_GET_LIMITATION_STATUS_CFM:
139 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 3)) {
143 int cfmSessionID = responseData.getTwoByteValue(0);
144 int cfmStatus = responseData.getOneByteValue(2);
147 logger.info("setResponse(): returned status: Error – Command rejected.");
151 logger.debug("setResponse(): returned status: OK - Command is accepted.");
152 if (!KLF200Response.check4matchingSessionID(logger, cfmSessionID, reqSessionID)) {
157 logger.warn("setResponse(): returned status={} (not defined).", cfmStatus);
163 case GW_LIMITATION_STATUS_NTF:
164 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 10)) {
167 // Extracting information items
168 int ntfSessionID = responseData.getTwoByteValue(0);
169 int ntfNodeID = responseData.getOneByteValue(2);
170 int ntfParameterID = responseData.getOneByteValue(3);
171 int ntfMinValue = responseData.getTwoByteValue(4);
172 int ntfMaxValue = responseData.getTwoByteValue(6);
173 int ntfLimitationOriginator = responseData.getOneByteValue(8);
174 int ntfLimitationTime = responseData.getOneByteValue(9);
176 if (!KLF200Response.check4matchingSessionID(logger, ntfSessionID, reqSessionID)) {
181 logger.trace("setResponse(): nodeId={}.", ntfNodeID);
182 logger.trace("setResponse(): ntfParameterID={}.", ntfParameterID);
183 logger.trace("setResponse(): ntfMinValue={}.", ntfMinValue);
184 logger.trace("setResponse(): ntfMaxValue={}.", ntfMaxValue);
185 logger.trace("setResponse(): ntfLimitationOriginator={}.", ntfLimitationOriginator);
186 logger.trace("setResponse(): ntfLimitationTime={}.", ntfLimitationTime);
188 // Determine the returned value
189 limitationValue = (reqLimitationType == 0) ? ntfMinValue : ntfMaxValue;
190 logger.debug("setResponse(): {} limitation for node {} is {}.",
191 (reqLimitationType == 0) ? "minimum" : "maximum", reqIndexArray01, limitationValue);
194 if (!isSequentialEnforced) {
196 "setResponse(): skipping wait for more packets as sequential processing is not enforced.");
201 case GW_COMMAND_RUN_STATUS_NTF:
202 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 13)) {
206 ntfSessionID = responseData.getTwoByteValue(0);
207 int ntfStatusiD = responseData.getOneByteValue(2);
208 int ntfIndex = responseData.getOneByteValue(3);
209 int ntfNodeParameter = responseData.getOneByteValue(4);
210 int ntfParameterValue = responseData.getTwoByteValue(5);
211 int ntfRunStatus = responseData.getOneByteValue(7);
212 int ntfStatusReply = responseData.getOneByteValue(8);
213 int ntfInformationCode = responseData.getFourByteValue(9);
214 // Extracting information items
215 logger.trace("setResponse(): ntfSessionID={} (requested {}).", ntfSessionID, reqSessionID);
216 logger.trace("setResponse(): ntfStatusiD={}.", ntfStatusiD);
217 logger.trace("setResponse(): ntfIndex={}.", ntfIndex);
218 logger.trace("setResponse(): ntfNodeParameter={}.", ntfNodeParameter);
219 logger.trace("setResponse(): ntfParameterValue={}.", ntfParameterValue);
220 logger.trace("setResponse(): ntfRunStatus={}.", ntfRunStatus);
221 logger.trace("setResponse(): ntfStatusReply={}.", ntfStatusReply);
222 logger.trace("setResponse(): ntfInformationCode={}.", ntfInformationCode);
224 if (!KLF200Response.check4matchingSessionID(logger, ntfSessionID, reqSessionID)) {
227 switch (ntfRunStatus) {
229 logger.debug("setResponse(): returned ntfRunStatus: EXECUTION_COMPLETED.");
233 logger.info("setResponse(): returned ntfRunStatus: EXECUTION_FAILED.");
237 logger.debug("setResponse(): returned ntfRunStatus: EXECUTION_ACTIVE.");
240 logger.warn("setResponse(): returned ntfRunStatus={} (not defined).", ntfRunStatus);
244 if (!isSequentialEnforced) {
246 "setResponse(): skipping wait for more packets as sequential processing is not enforced.");
252 case GW_SESSION_FINISHED_NTF:
254 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 2)) {
257 int finishedNtfSessionID = responseData.getTwoByteValue(0);
258 if (!KLF200Response.check4matchingSessionID(logger, finishedNtfSessionID, reqSessionID)) {
261 logger.debug("setResponse(): finishedNtfSessionID={}.", finishedNtfSessionID);
266 KLF200Response.errorLogging(logger, responseCommand);
268 KLF200Response.outroLogging(logger, success, finished);
272 public boolean isCommunicationFinished() {
277 public boolean isCommunicationSuccessful() {
282 * ===========================================================
283 * Methods in addition to the interface {@link BridgeCommunicationProtocol}
284 * and the abstract class {@link GetProductLimitation}
288 public void setActuatorIdAndLimitationType(int nodeId, boolean limitationMinimum) {
289 logger.trace("setProductId({},{}) called.", nodeId, limitationMinimum);
290 this.reqIndexArray01 = nodeId;
291 this.reqLimitationType = limitationMinimum ? 0 : 1;
296 public int getLimitation() {
297 return limitationValue;