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.SetProductLimitation;
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.openhab.binding.velux.internal.things.VeluxProductPosition;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Protocol specific bridge communication supported by the Velux bridge:
29 * <B>Modify Product Limitations</B>
31 * Common Message semantic: Communication with the bridge and (optionally) storing returned information within the class
34 * As 3rd level class it defines informations how to send query and receive answer through the
35 * {@link org.openhab.binding.velux.internal.bridge.VeluxBridgeProvider VeluxBridgeProvider}
36 * as described by the interface {@link SlipBridgeCommunicationProtocol}.
38 * Methods in addition to the mentioned interface:
40 * <LI>{@link #setActuatorIdAndMinimumLimitation} to set the lower limitation of one specific product.</LI>
41 * <LI>{@link #setActuatorIdAndMaximumLimitation} to set the higher limitation of one specific product.</LI>
42 * <LI>{@link #setActuatorIdAndResetLimitation} to reset any limitation of one specific product.</LI>
45 * @see SetProductLimitation
46 * @see SlipBridgeCommunicationProtocol
48 * @author Guenther Schreiner - Initial contribution.
51 class SCsetLimitation extends SetProductLimitation implements SlipBridgeCommunicationProtocol {
52 private final Logger logger = LoggerFactory.getLogger(SCsetLimitation.class);
54 private static final String DESCRIPTION = "Modify Actuator Limitation";
55 private static final Command COMMAND = Command.GW_SET_LIMITATION_REQ;
58 * ===========================================================
59 * Message Content Parameters
62 private int reqSessionID = 0;
63 private int reqCommandOriginator = 8; // SAAC
64 private int reqPriorityLevel = 5; // Comfort Level 2
65 private int reqIndexArrayCount = 1; // One node will be addressed
66 private int reqIndexArray01 = 1; // This is the node
67 private int reqParameterID = 0; // MP = Main parameter
68 private int reqLimitationValueMin = VeluxProductPosition.VPP_VELUX_IGNORE; // will be set lateron
69 private int reqLimitationValueMax = VeluxProductPosition.VPP_VELUX_IGNORE; // will be set lateron
70 private int reqLimitationTime = 0; // 0 = 30 seconds, 1 = 60 seconds, ..., 253 = unlimited, 254 = clear entry for
71 // the Master, 255 = clear all
74 * ===========================================================
78 private byte[] requestData = new byte[0];
81 * ===========================================================
85 private boolean success = false;
86 private boolean finished = false;
89 * ===========================================================
93 public SCsetLimitation() {
94 logger.debug("SCsetLimitation(Constructor) called.");
95 Random rand = new Random();
96 reqSessionID = rand.nextInt(0x0fff);
97 logger.debug("SCsetLimitation(): starting sessions with the random number {}.", reqSessionID);
101 * ===========================================================
102 * Methods required for interface {@link BridgeCommunicationProtocol}.
106 public String name() {
111 public CommandNumber getRequestCommand() {
114 logger.debug("getRequestCommand() returns {} ({}).", COMMAND.name(), COMMAND.getCommand());
115 return COMMAND.getCommand();
119 public byte[] getRequestDataAsArrayOfBytes() {
120 Packet request = new Packet(new byte[31]);
121 reqSessionID = (reqSessionID + 1) & 0xffff;
122 request.setTwoByteValue(0, reqSessionID);
123 request.setOneByteValue(2, reqCommandOriginator);
124 request.setOneByteValue(3, reqPriorityLevel);
125 request.setOneByteValue(4, reqIndexArrayCount);
126 request.setOneByteValue(5, reqIndexArray01);
127 request.setOneByteValue(25, reqParameterID);
128 request.setTwoByteValue(26, reqLimitationValueMin);
129 request.setTwoByteValue(28, reqLimitationValueMax);
130 request.setOneByteValue(30, reqLimitationTime);
131 logger.trace("getRequestDataAsArrayOfBytes(): ntfSessionID={}.", reqSessionID);
132 logger.trace("getRequestDataAsArrayOfBytes(): reqCommandOriginator={}.", reqCommandOriginator);
133 logger.trace("getRequestDataAsArrayOfBytes(): reqPriorityLevel={}.", reqPriorityLevel);
134 logger.trace("getRequestDataAsArrayOfBytes(): reqIndexArrayCount={}.", reqIndexArrayCount);
135 logger.trace("getRequestDataAsArrayOfBytes(): reqIndexArray01={}.", reqIndexArray01);
136 logger.trace("getRequestDataAsArrayOfBytes(): reqParameterID={}.", reqParameterID);
137 logger.trace("getRequestDataAsArrayOfBytes(): reqLimitationValueMin={}.", reqLimitationValueMin);
138 logger.trace("getRequestDataAsArrayOfBytes(): reqLimitationValueMax={}.", reqLimitationValueMax);
139 logger.trace("getRequestDataAsArrayOfBytes(): reqLimitationTime={}.", reqLimitationTime);
140 requestData = request.toByteArray();
141 logger.trace("getRequestDataAsArrayOfBytes() data is {}.", new Packet(requestData).toString());
146 public void setResponse(short responseCommand, byte[] thisResponseData, boolean isSequentialEnforced) {
147 KLF200Response.introLogging(logger, responseCommand, thisResponseData);
150 Packet responseData = new Packet(thisResponseData);
151 switch (Command.get(responseCommand)) {
152 case GW_SET_LIMITATION_CFM:
153 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 3)) {
157 int cfmSessionID = responseData.getTwoByteValue(0);
158 int cfmStatus = responseData.getOneByteValue(2);
161 logger.info("setResponse(): returned status: Error – Command rejected.");
165 logger.debug("setResponse(): returned status: OK - Command is accepted.");
166 if (!KLF200Response.check4matchingSessionID(logger, cfmSessionID, reqSessionID)) {
171 logger.warn("setResponse(): returned status={} (not defined).", cfmStatus);
177 case GW_LIMITATION_STATUS_NTF:
178 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 10)) {
181 // Extracting information items
182 int ntfSessionID = responseData.getTwoByteValue(0);
183 int ntfNodeID = responseData.getOneByteValue(2);
184 int ntfParameterID = responseData.getOneByteValue(3);
185 int ntfMinValue = responseData.getTwoByteValue(4);
186 int ntfMaxValue = responseData.getTwoByteValue(6);
187 int ntfLimitationOriginator = responseData.getOneByteValue(8);
188 int ntfLimitationTime = responseData.getOneByteValue(9);
189 logger.trace("setResponse(): nodeId={}.", ntfNodeID);
190 logger.trace("setResponse(): ntfParameterID={}.", ntfParameterID);
191 logger.trace("setResponse(): ntfMinValue={}.", ntfMinValue);
192 logger.trace("setResponse(): ntfMaxValue={}.", ntfMaxValue);
193 logger.trace("setResponse(): ntfLimitationOriginator={}.", ntfLimitationOriginator);
194 logger.trace("setResponse(): ntfLimitationTime={}.", ntfLimitationTime);
196 if (!KLF200Response.check4matchingSessionID(logger, ntfSessionID, reqSessionID)) {
201 if (!isSequentialEnforced) {
203 "setResponse(): skipping wait for more packets as sequential processing is not enforced.");
208 case GW_COMMAND_RUN_STATUS_NTF:
209 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 13)) {
213 ntfSessionID = responseData.getTwoByteValue(0);
214 int ntfStatusiD = responseData.getOneByteValue(2);
215 int ntfIndex = responseData.getOneByteValue(3);
216 int ntfNodeParameter = responseData.getOneByteValue(4);
217 int ntfParameterValue = responseData.getTwoByteValue(5);
218 int ntfRunStatus = responseData.getOneByteValue(7);
219 int ntfStatusReply = responseData.getOneByteValue(8);
220 int ntfInformationCode = responseData.getFourByteValue(9);
221 // Extracting information items
222 logger.trace("setResponse(): ntfSessionID={} (requested {}).", ntfSessionID, reqSessionID);
223 logger.trace("setResponse(): ntfStatusiD={}.", ntfStatusiD);
224 logger.trace("setResponse(): ntfIndex={}.", ntfIndex);
225 logger.trace("setResponse(): ntfNodeParameter={}.", ntfNodeParameter);
226 logger.trace("setResponse(): ntfParameterValue={}.", ntfParameterValue);
227 logger.trace("setResponse(): ntfRunStatus={}.", ntfRunStatus);
228 logger.trace("setResponse(): ntfStatusReply={}.", ntfStatusReply);
229 logger.trace("setResponse(): ntfInformationCode={}.", ntfInformationCode);
231 if (!KLF200Response.check4matchingSessionID(logger, ntfSessionID, reqSessionID)) {
234 switch (ntfRunStatus) {
236 logger.debug("setResponse(): returned ntfRunStatus: EXECUTION_COMPLETED.");
240 logger.info("setResponse(): returned ntfRunStatus: EXECUTION_FAILED.");
244 logger.debug("setResponse(): returned ntfRunStatus: EXECUTION_ACTIVE.");
247 logger.warn("setResponse(): returned ntfRunStatus={} (not defined).", ntfRunStatus);
251 if (!isSequentialEnforced) {
253 "setResponse(): skipping wait for more packets as sequential processing is not enforced.");
259 case GW_SESSION_FINISHED_NTF:
261 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 2)) {
264 int finishedNtfSessionID = responseData.getTwoByteValue(0);
265 if (!KLF200Response.check4matchingSessionID(logger, finishedNtfSessionID, reqSessionID)) {
268 logger.debug("setResponse(): finishedNtfSessionID={}.", finishedNtfSessionID);
273 KLF200Response.errorLogging(logger, responseCommand);
275 KLF200Response.outroLogging(logger, success, finished);
279 public boolean isCommunicationFinished() {
284 public boolean isCommunicationSuccessful() {
289 * ===========================================================
290 * Methods in addition to the interface {@link BridgeCommunicationProtocol}
291 * and the abstract class {@link SetProductLimitation}
295 public void setActuatorIdAndMinimumLimitation(int nodeId, int limitation) {
296 logger.trace("setActuatorIdAndLimitationTypeAndLimitation({},{}) called.", nodeId, limitation);
297 reqIndexArray01 = nodeId;
298 reqLimitationValueMin = limitation;
299 reqLimitationValueMax = VeluxProductPosition.VPP_VELUX_IGNORE;
304 public void setActuatorIdAndMaximumLimitation(int nodeId, int limitation) {
305 logger.trace("setActuatorIdAndLimitationTypeAndLimitation({},{}) called.", nodeId, limitation);
306 reqIndexArray01 = nodeId;
307 reqLimitationValueMin = VeluxProductPosition.VPP_VELUX_IGNORE;
308 reqLimitationValueMax = limitation;
312 public void setActuatorIdAndResetLimitation(int nodeId) {
313 logger.trace("setActuatorIdAndResetLimitation({}) called.", nodeId);
314 reqIndexArray01 = nodeId;
315 reqLimitationValueMin = VeluxProductPosition.VPP_VELUX_IGNORE;
316 reqLimitationValueMax = VeluxProductPosition.VPP_VELUX_IGNORE;