]> git.basschouten.com Git - openhab-addons.git/blob
a375c7696dad8555a2af788cdd38fdeaf7df806c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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 org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.velux.internal.bridge.common.GetProduct;
17 import org.openhab.binding.velux.internal.bridge.slip.utils.KLF200Response;
18 import org.openhab.binding.velux.internal.bridge.slip.utils.Packet;
19 import org.openhab.binding.velux.internal.things.VeluxKLFAPI.Command;
20 import org.openhab.binding.velux.internal.things.VeluxKLFAPI.CommandNumber;
21 import org.openhab.binding.velux.internal.things.VeluxProduct;
22 import org.openhab.binding.velux.internal.things.VeluxProduct.ProductBridgeIndex;
23 import org.openhab.binding.velux.internal.things.VeluxProductName;
24 import org.openhab.binding.velux.internal.things.VeluxProductSerialNo;
25 import org.openhab.binding.velux.internal.things.VeluxProductType;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * Protocol specific bridge communication supported by the Velux bridge:
31  * <B>Retrieve Product</B>
32  * <P>
33  * Common Message semantic: Communication with the bridge and (optionally) storing returned information within the class
34  * itself.
35  * <P>
36  * As 3rd level class it defines informations how to send query and receive answer through the
37  * {@link org.openhab.binding.velux.internal.bridge.VeluxBridgeProvider VeluxBridgeProvider}
38  * as described by the {@link org.openhab.binding.velux.internal.bridge.slip.SlipBridgeCommunicationProtocol
39  * SlipBridgeCommunicationProtocol}.
40  * <P>
41  * Methods in addition to the mentioned interface:
42  * <UL>
43  * <LI>{@link #setProductId(int)} to define the one specific product.</LI>
44  * <LI>{@link #getProduct} to retrieve one specific product.</LI>
45  * </UL>
46  *
47  * @see GetProduct
48  * @see SlipBridgeCommunicationProtocol
49  *
50  * @author Guenther Schreiner - Initial contribution.
51  */
52 @NonNullByDefault
53 class SCgetProduct extends GetProduct implements SlipBridgeCommunicationProtocol {
54     private final Logger logger = LoggerFactory.getLogger(SCgetProduct.class);
55
56     private static final String DESCRIPTION = "Retrieve Product";
57     private static final Command COMMAND = Command.GW_GET_NODE_INFORMATION_REQ;
58
59     /*
60      * ===========================================================
61      * Message Content Parameters
62      */
63
64     private int reqNodeID;
65
66     /*
67      * ===========================================================
68      * Message Objects
69      */
70
71     private byte[] requestData = new byte[0];
72
73     /*
74      * ===========================================================
75      * Result Objects
76      */
77
78     private boolean success = false;
79     private boolean finished = false;
80
81     private VeluxProduct product = VeluxProduct.UNKNOWN;
82
83     /*
84      * ===========================================================
85      * Methods required for interface {@link BridgeCommunicationProtocol}.
86      */
87
88     @Override
89     public String name() {
90         return DESCRIPTION;
91     }
92
93     @Override
94     public CommandNumber getRequestCommand() {
95         success = false;
96         finished = false;
97         logger.debug("getRequestCommand() returns {} ({}).", COMMAND.name(), COMMAND.getCommand());
98         return COMMAND.getCommand();
99     }
100
101     @Override
102     public byte[] getRequestDataAsArrayOfBytes() {
103         logger.trace("getRequestDataAsArrayOfBytes() returns data for retrieving node with id {}.", reqNodeID);
104         Packet request = new Packet(new byte[1]);
105         request.setOneByteValue(0, reqNodeID);
106         requestData = request.toByteArray();
107         return requestData;
108     }
109
110     @Override
111     public void setResponse(short responseCommand, byte[] thisResponseData, boolean isSequentialEnforced) {
112         KLF200Response.introLogging(logger, responseCommand, thisResponseData);
113         success = false;
114         finished = false;
115         Packet responseData = new Packet(thisResponseData);
116         switch (Command.get(responseCommand)) {
117             case GW_GET_NODE_INFORMATION_CFM:
118                 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 2)) {
119                     finished = true;
120                     break;
121                 }
122                 int cfmStatus = responseData.getOneByteValue(0);
123                 int cfmNodeID = responseData.getOneByteValue(1);
124                 switch (cfmStatus) {
125                     case 0:
126                         logger.trace("setResponse(): returned status: OK - Request accepted.");
127                         if (!KLF200Response.check4matchingNodeID(logger, reqNodeID, cfmNodeID)) {
128                             finished = true;
129                         }
130                         break;
131                     case 1:
132                         finished = true;
133                         logger.trace("setResponse(): returned status: Error – Request rejected.");
134                         break;
135                     case 2:
136                         finished = true;
137                         logger.trace("setResponse(): returned status: Error – Invalid node index.");
138                         break;
139                     default:
140                         finished = true;
141                         logger.warn("setResponse({}): returned status={} (Reserved/unknown).",
142                                 Command.get(responseCommand).toString(), cfmStatus);
143                         break;
144                 }
145                 break;
146
147             case GW_GET_NODE_INFORMATION_NTF:
148                 finished = true;
149                 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 124)) {
150                     break;
151                 }
152                 // Extracting information items
153                 int ntfNodeID = responseData.getOneByteValue(0);
154                 logger.trace("setResponse(): ntfNodeID={}.", ntfNodeID);
155                 int ntfOrder = responseData.getTwoByteValue(1);
156                 logger.trace("setResponse(): ntfOrder={}.", ntfOrder);
157                 int ntfPlacement = responseData.getOneByteValue(3);
158                 logger.trace("setResponse(): ntfPlacement={}.", ntfPlacement);
159                 String ntfName = responseData.getString(4, 64);
160                 logger.trace("setResponse(): ntfName={}.", ntfName);
161                 int ntfVelocity = responseData.getOneByteValue(68);
162                 logger.trace("setResponse(): ntfVelocity={}.", ntfVelocity);
163                 int ntfNodeTypeSubType = responseData.getTwoByteValue(69);
164                 logger.trace("setResponse(): ntfNodeTypeSubType={} ({}).", ntfNodeTypeSubType,
165                         VeluxProductType.get(ntfNodeTypeSubType));
166                 logger.trace("setResponse(): derived product description={}.",
167                         VeluxProductType.toString(ntfNodeTypeSubType));
168                 int ntfProductGroup = responseData.getTwoByteValue(71);
169                 logger.trace("setResponse(): ntfProductGroup={}.", ntfProductGroup);
170                 int ntfProductType = responseData.getOneByteValue(72);
171                 logger.trace("setResponse(): ntfProductType={}.", ntfProductType);
172                 int ntfNodeVariation = responseData.getOneByteValue(73);
173                 logger.trace("setResponse(): ntfNodeVariation={}.", ntfNodeVariation);
174                 int ntfPowerMode = responseData.getOneByteValue(74);
175                 logger.trace("setResponse(): ntfPowerMode={}.", ntfPowerMode);
176                 int ntfBuildNumber = responseData.getOneByteValue(75);
177                 logger.trace("setResponse(): ntfBuildNumber={}.", ntfBuildNumber);
178                 byte[] ntfSerialNumber = responseData.getByteArray(76, 8);
179                 logger.trace("setResponse(): ntfSerialNumber={}.", ntfSerialNumber);
180                 int ntfState = responseData.getOneByteValue(84);
181                 logger.trace("setResponse(): ntfState={}.", ntfState);
182                 int ntfCurrentPosition = responseData.getTwoByteValue(85);
183                 logger.trace("setResponse(): ntfCurrentPosition={}.", ntfCurrentPosition);
184                 int ntfTarget = responseData.getTwoByteValue(87);
185                 logger.trace("setResponse(): ntfTarget={}.", ntfTarget);
186                 int ntfFP1CurrentPosition = responseData.getTwoByteValue(89);
187                 logger.trace("setResponse(): ntfFP1CurrentPosition={}.", ntfFP1CurrentPosition);
188                 int ntfFP2CurrentPosition = responseData.getTwoByteValue(91);
189                 logger.trace("setResponse(): ntfFP2CurrentPosition={}.", ntfFP2CurrentPosition);
190                 int ntfFP3CurrentPosition = responseData.getTwoByteValue(93);
191                 logger.trace("setResponse(): ntfFP3CurrentPosition={}.", ntfFP3CurrentPosition);
192                 int ntfFP4CurrentPosition = responseData.getTwoByteValue(95);
193                 logger.trace("setResponse(): ntfFP4CurrentPosition={}.", ntfFP4CurrentPosition);
194                 int ntfRemainingTime = responseData.getFourByteValue(97);
195                 logger.trace("setResponse(): ntfRemainingTime={}.", ntfRemainingTime);
196                 int ntfTimeStamp = responseData.getFourByteValue(99);
197                 logger.trace("setResponse(): ntfTimeStamp={}.", ntfTimeStamp);
198                 int ntfNbrOfAlias = responseData.getOneByteValue(103);
199                 logger.trace("setResponse(): ntfNbrOfAlias={}.", ntfNbrOfAlias);
200                 int ntfAliasOne = responseData.getFourByteValue(104);
201                 logger.trace("setResponse(): ntfAliasOne={}.", ntfAliasOne);
202                 int ntfAliasTwo = responseData.getFourByteValue(108);
203                 logger.trace("setResponse(): ntfAliasTwo={}.", ntfAliasTwo);
204                 int ntfAliasThree = responseData.getFourByteValue(112);
205                 logger.trace("setResponse(): ntfAliasThree={}.", ntfAliasThree);
206                 int ntfAliasFour = responseData.getFourByteValue(116);
207                 logger.trace("setResponse(): ntfAliasFour={}.", ntfAliasFour);
208                 int ntfAliasFive = responseData.getFourByteValue(120);
209                 logger.trace("setResponse(): ntfAliasFive={}.", ntfAliasFive);
210
211                 if (!KLF200Response.check4matchingNodeID(logger, reqNodeID, ntfNodeID)) {
212                     break;
213                 }
214
215                 if ((ntfName.length() == 0) || ntfName.startsWith("_")) {
216                     ntfName = "#".concat(String.valueOf(ntfNodeID));
217                     logger.debug("setResponse(): device provided invalid name, using '{}' instead.", ntfName);
218                 }
219                 String commonSerialNumber = VeluxProductSerialNo.toString(ntfSerialNumber);
220                 if (VeluxProductSerialNo.isInvalid(ntfSerialNumber)) {
221                     commonSerialNumber = new String(ntfName);
222                     logger.debug("setResponse(): device provided invalid serial number, using name '{}' instead.",
223                             commonSerialNumber);
224                 }
225
226                 product = new VeluxProduct(new VeluxProductName(ntfName), VeluxProductType.get(ntfNodeTypeSubType),
227                         new ProductBridgeIndex(ntfNodeID), ntfOrder, ntfPlacement, ntfVelocity, ntfNodeVariation,
228                         ntfPowerMode, commonSerialNumber, ntfState, ntfCurrentPosition, ntfTarget, ntfRemainingTime,
229                         ntfTimeStamp);
230                 success = true;
231                 break;
232
233             default:
234                 KLF200Response.errorLogging(logger, responseCommand);
235         }
236         KLF200Response.outroLogging(logger, success, finished);
237     }
238
239     @Override
240     public boolean isCommunicationFinished() {
241         return finished;
242     }
243
244     @Override
245     public boolean isCommunicationSuccessful() {
246         return success;
247     }
248
249     /*
250      * ===========================================================
251      * Methods in addition to the interface {@link BridgeCommunicationProtocol}
252      * and the abstract class {@link GetProduct}
253      */
254
255     @Override
256     public void setProductId(int nodeId) {
257         logger.trace("setProductId({}) called.", nodeId);
258         this.reqNodeID = nodeId;
259         return;
260     }
261
262     @Override
263     public VeluxProduct getProduct() {
264         logger.trace("getProduct(): returning product {}.", product);
265         return product;
266     }
267 }