]> git.basschouten.com Git - openhab-addons.git/blob
1803e3d742e4142ead863afd0984784b338dedc9
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.bridge.slip;
14
15 import java.util.Random;
16
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;
25
26 /**
27  * Protocol specific bridge communication supported by the Velux bridge:
28  * <B>Retrieve Product Limitations</B>
29  * <P>
30  * Common Message semantic: Communication with the bridge and (optionally) storing returned information within the class
31  * itself.
32  * <P>
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}.
36  * <P>
37  * Methods in addition to the mentioned interface:
38  * <UL>
39  * <LI>{@link #setActuatorIdAndLimitationType(int,boolean)} to define the one specific product.</LI>
40  * </UL>
41  *
42  * @see GetProductLimitation
43  * @see SlipBridgeCommunicationProtocol
44  *
45  * @author Guenther Schreiner - Initial contribution.
46  */
47 @NonNullByDefault
48 class SCgetLimitation extends GetProductLimitation implements SlipBridgeCommunicationProtocol {
49     private final Logger logger = LoggerFactory.getLogger(SCgetLimitation.class);
50
51     private static final String DESCRIPTION = "Retrieve Actuator Limitation";
52     private static final Command COMMAND = Command.GW_GET_LIMITATION_STATUS_REQ;
53
54     /*
55      * ===========================================================
56      * Message Content Parameters
57      */
58
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.
64
65     /*
66      * ===========================================================
67      * Message Objects
68      */
69
70     private byte[] requestData = new byte[0];
71
72     /*
73      * ===========================================================
74      * Result Objects
75      */
76
77     private boolean success = false;
78     private boolean finished = false;
79
80     private int limitationValue = 0;
81
82     /*
83      * ===========================================================
84      * Constructor Method
85      */
86
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);
92     }
93
94     /*
95      * ===========================================================
96      * Methods required for interface {@link BridgeCommunicationProtocol}.
97      */
98
99     @Override
100     public String name() {
101         return DESCRIPTION;
102     }
103
104     @Override
105     public CommandNumber getRequestCommand() {
106         success = false;
107         finished = false;
108         logger.debug("getRequestCommand() returns {} ({}).", COMMAND.name(), COMMAND.getCommand());
109         return COMMAND.getCommand();
110     }
111
112     @Override
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());
128         return requestData;
129     }
130
131     @Override
132     public void setResponse(short responseCommand, byte[] thisResponseData, boolean isSequentialEnforced) {
133         KLF200Response.introLogging(logger, responseCommand, thisResponseData);
134         success = false;
135         finished = false;
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)) {
140                     finished = true;
141                     break;
142                 }
143                 int cfmSessionID = responseData.getTwoByteValue(0);
144                 int cfmStatus = responseData.getOneByteValue(2);
145                 switch (cfmStatus) {
146                     case 0:
147                         logger.info("setResponse(): returned status: Error – Command rejected.");
148                         finished = true;
149                         break;
150                     case 1:
151                         logger.debug("setResponse(): returned status: OK - Command is accepted.");
152                         if (!KLF200Response.check4matchingSessionID(logger, cfmSessionID, reqSessionID)) {
153                             finished = true;
154                         }
155                         break;
156                     default:
157                         logger.warn("setResponse(): returned status={} (not defined).", cfmStatus);
158                         finished = true;
159                         break;
160                 }
161                 break;
162
163             case GW_LIMITATION_STATUS_NTF:
164                 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 10)) {
165                     break;
166                 }
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);
175
176                 if (!KLF200Response.check4matchingSessionID(logger, ntfSessionID, reqSessionID)) {
177                     finished = true;
178                     break;
179                 }
180
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);
187
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);
192
193                 success = true;
194                 if (!isSequentialEnforced) {
195                     logger.trace(
196                             "setResponse(): skipping wait for more packets as sequential processing is not enforced.");
197                     finished = true;
198                 }
199                 break;
200
201             case GW_COMMAND_RUN_STATUS_NTF:
202                 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 13)) {
203                     finished = true;
204                     break;
205                 }
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);
223
224                 if (!KLF200Response.check4matchingSessionID(logger, ntfSessionID, reqSessionID)) {
225                     finished = true;
226                 }
227                 switch (ntfRunStatus) {
228                     case 0:
229                         logger.debug("setResponse(): returned ntfRunStatus: EXECUTION_COMPLETED.");
230                         success = true;
231                         break;
232                     case 1:
233                         logger.info("setResponse(): returned ntfRunStatus: EXECUTION_FAILED.");
234                         finished = true;
235                         break;
236                     case 2:
237                         logger.debug("setResponse(): returned ntfRunStatus: EXECUTION_ACTIVE.");
238                         break;
239                     default:
240                         logger.warn("setResponse(): returned ntfRunStatus={} (not defined).", ntfRunStatus);
241                         finished = true;
242                         break;
243                 }
244                 if (!isSequentialEnforced) {
245                     logger.trace(
246                             "setResponse(): skipping wait for more packets as sequential processing is not enforced.");
247                     success = true;
248                     finished = true;
249                 }
250                 break;
251
252             case GW_SESSION_FINISHED_NTF:
253                 finished = true;
254                 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 2)) {
255                     break;
256                 }
257                 int finishedNtfSessionID = responseData.getTwoByteValue(0);
258                 if (!KLF200Response.check4matchingSessionID(logger, finishedNtfSessionID, reqSessionID)) {
259                     break;
260                 }
261                 logger.debug("setResponse(): finishedNtfSessionID={}.", finishedNtfSessionID);
262                 success = true;
263                 break;
264
265             default:
266                 KLF200Response.errorLogging(logger, responseCommand);
267         }
268         KLF200Response.outroLogging(logger, success, finished);
269     }
270
271     @Override
272     public boolean isCommunicationFinished() {
273         return finished;
274     }
275
276     @Override
277     public boolean isCommunicationSuccessful() {
278         return success;
279     }
280
281     /*
282      * ===========================================================
283      * Methods in addition to the interface {@link BridgeCommunicationProtocol}
284      * and the abstract class {@link GetProductLimitation}
285      */
286
287     @Override
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;
292         return;
293     }
294
295     @Override
296     public int getLimitation() {
297         return limitationValue;
298     }
299 }