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.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;
27 * Protocol specific bridge communication supported by the Velux bridge:
28 * <B>Identify Product</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 {@link org.openhab.binding.velux.internal.bridge.slip.SlipBridgeCommunicationProtocol
36 * SlipBridgeCommunicationProtocol}.
38 * Methods in addition to the mentioned interface:
40 * <LI>{@link #setProductId(int)} to define the intended product.</LI>
43 * @see RunProductIdentification
44 * @see SlipBridgeCommunicationProtocol
46 * @author Guenther Schreiner - Initial contribution.
49 class SCrunProductIdentification extends RunProductIdentification implements SlipBridgeCommunicationProtocol {
50 private final Logger logger = LoggerFactory.getLogger(SCrunProductIdentification.class);
52 private static final String DESCRIPTION = "Identify Product";
53 private static final Command COMMAND = Command.GW_WINK_SEND_REQ;
56 * ===========================================================
57 * Message Content Parameters
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
69 * ===========================================================
73 private byte[] requestData = new byte[0];
76 * ===========================================================
80 private boolean success = false;
81 private boolean finished = false;
84 * ===========================================================
91 * Initializes the session id {@link #reqSessionID} with a random start value.
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);
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[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());
135 public void setResponse(short responseCommand, byte[] thisResponseData, boolean isSequentialEnforced) {
136 KLF200Response.introLogging(logger, responseCommand, thisResponseData);
139 Packet responseData = new Packet(thisResponseData);
140 switch (Command.get(responseCommand)) {
141 case GW_WINK_SEND_CFM:
143 if (!KLF200Response.isLengthValid(logger, responseCommand, thisResponseData, 3)) {
146 int cfmSessionID = responseData.getTwoByteValue(0);
147 int cfmStatus = responseData.getOneByteValue(2);
150 logger.trace("setResponse(): returned status: Error - Wink is rejected.");
153 if (!KLF200Response.check4matchingSessionID(logger, cfmSessionID, reqSessionID)) {
156 logger.trace("setResponse(): returned status: OK – Wink is accepted.");
160 logger.warn("setResponse({}): returned status={} (Reserved/unknown).",
161 Command.get(responseCommand).toString(), cfmStatus);
167 KLF200Response.errorLogging(logger, responseCommand);
170 KLF200Response.outroLogging(logger, success, finished);
174 public boolean isCommunicationFinished() {
179 public boolean isCommunicationSuccessful() {
184 * ===========================================================
185 * Methods in addition to the interface {@link BridgeCommunicationProtocol}
186 * and the abstract class {@link RunProductIdentification}
190 * Constructor Addon Method.
192 * Passes the intended Actuator Identifier towards this class for building the request.
194 * @param actuatorId as type int describing the scene to be processed.
195 * @return <b>this</b> of type {@link SCrunProductIdentification} as class itself.
198 public SCrunProductIdentification setProductId(int actuatorId) {
199 logger.trace("setProductId({}) called.", actuatorId);
200 this.reqIndexValue0 = actuatorId;