]> git.basschouten.com Git - openhab-addons.git/blob
1a7eb1e5d956eafd608fce0a771dab57662e9e0e
[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.RunProductIdentification;
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>Identify Product</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 {@link org.openhab.binding.velux.internal.bridge.slip.SlipBridgeCommunicationProtocol
36  * SlipBridgeCommunicationProtocol}.
37  * <P>
38  * Methods in addition to the mentioned interface:
39  * <UL>
40  * <LI>{@link #setProductId(int)} to define the intended product.</LI>
41  * </UL>
42  *
43  * @see RunProductIdentification
44  * @see SlipBridgeCommunicationProtocol
45  *
46  * @author Guenther Schreiner - Initial contribution.
47  */
48 @NonNullByDefault
49 class SCrunProductIdentification extends RunProductIdentification implements SlipBridgeCommunicationProtocol {
50     private final Logger logger = LoggerFactory.getLogger(SCrunProductIdentification.class);
51
52     private static final String DESCRIPTION = "Identify Product";
53     private static final Command COMMAND = Command.GW_WINK_SEND_REQ;
54
55     /*
56      * ===========================================================
57      * Message Content Parameters
58      */
59
60     private int reqSessionID = 0;
61     private int reqCommandOriginator = 8; // SAAC
62     private int reqPriorityLevel = 5; // Comfort Level 2
63     private int reqWinkState = 1; // Enable wink
64     private int reqWinkTime = 2; // Winktime = 2 seconds
65     private int reqIndexArrayCount = 1; // Number of actuators to be winking
66     private int reqIndexValue0 = 0; // Value for the ONE actuator
67
68     /*
69      * ===========================================================
70      * Message Objects
71      */
72
73     private byte[] requestData = new byte[0];
74
75     /*
76      * ===========================================================
77      * Result Objects
78      */
79
80     private boolean success = false;
81     private boolean finished = false;
82
83     /*
84      * ===========================================================
85      * Constructor Method
86      */
87
88     /**
89      * Constructor.
90      * <P>
91      * Initializes the session id {@link #reqSessionID} with a random start value.
92      */
93     public SCrunProductIdentification() {
94         logger.debug("SCrunProductIdentification(Constructor) called.");
95         Random rand = new Random();
96         reqSessionID = rand.nextInt(0x0fff);
97         logger.debug("SCrunProductIdentification(): starting sessions with the random number {}.", reqSessionID);
98     }
99
100     /*
101      * ===========================================================
102      * Methods required for interface {@link BridgeCommunicationProtocol}.
103      */
104
105     @Override
106     public String name() {
107         return DESCRIPTION;
108     }
109
110     @Override
111     public CommandNumber getRequestCommand() {
112         success = false;
113         finished = false;
114         logger.debug("getRequestCommand() returns {} ({}).", COMMAND.name(), COMMAND.getCommand());
115         return COMMAND.getCommand();
116     }
117
118     @Override
119     public byte[] getRequestDataAsArrayOfBytes() {
120         Packet request = new Packet(new byte[27]);
121         reqSessionID = (reqSessionID + 1) & 0xffff;
122         request.setTwoByteValue(0, reqSessionID);
123         request.setOneByteValue(2, reqCommandOriginator);
124         request.setOneByteValue(3, reqPriorityLevel);
125         request.setOneByteValue(4, reqWinkState);
126         request.setOneByteValue(5, reqWinkTime);
127         request.setOneByteValue(6, reqIndexArrayCount);
128         request.setTwoByteValue(7, reqIndexValue0);
129         requestData = request.toByteArray();
130         logger.trace("getRequestDataAsArrayOfBytes() data is {}.", new Packet(requestData).toString());
131         return requestData;
132     }
133
134     @Override
135     public void setResponse(short responseCommand, byte[] thisResponseData, boolean isSequentialEnforced) {
136         KLF200Response.introLogging(logger, responseCommand, thisResponseData);
137         success = false;
138         finished = false;
139         Packet responseData = new Packet(thisResponseData);
140         switch (Command.get(responseCommand)) {
141             case GW_WINK_SEND_CFM:
142                 finished = true;
143                 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 3)) {
144                     break;
145                 }
146                 int cfmSessionID = responseData.getTwoByteValue(0);
147                 int cfmStatus = responseData.getOneByteValue(2);
148                 switch (cfmStatus) {
149                     case 0:
150                         logger.trace("setResponse(): returned status: Error - Wink is rejected.");
151                         break;
152                     case 1:
153                         if (!KLF200Response.check4matchingSessionID(logger, cfmSessionID, reqSessionID)) {
154                             break;
155                         }
156                         logger.trace("setResponse(): returned status: OK – Wink is accepted.");
157                         success = true;
158                         break;
159                     default:
160                         logger.warn("setResponse({}): returned status={} (Reserved/unknown).",
161                                 Command.get(responseCommand).toString(), cfmStatus);
162                         break;
163                 }
164                 break;
165
166             default:
167                 KLF200Response.errorLogging(logger, responseCommand);
168                 finished = true;
169         }
170         KLF200Response.outroLogging(logger, success, finished);
171     }
172
173     @Override
174     public boolean isCommunicationFinished() {
175         return finished;
176     }
177
178     @Override
179     public boolean isCommunicationSuccessful() {
180         return success;
181     }
182
183     /*
184      * ===========================================================
185      * Methods in addition to the interface {@link BridgeCommunicationProtocol}
186      * and the abstract class {@link RunProductIdentification}
187      */
188
189     /**
190      * Constructor Addon Method.
191      * <P>
192      * Passes the intended Actuator Identifier towards this class for building the request.
193      *
194      * @param actuatorId as type int describing the scene to be processed.
195      * @return <b>this</b> of type {@link SCrunProductIdentification} as class itself.
196      */
197     @Override
198     public SCrunProductIdentification setProductId(int actuatorId) {
199         logger.trace("setProductId({}) called.", actuatorId);
200         this.reqIndexValue0 = actuatorId;
201         return this;
202     }
203 }