]> git.basschouten.com Git - openhab-addons.git/blob
c9c932a972bc2b378173b1a5ff1cec1c0905f1f8
[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.homematic.internal.communicator.client;
14
15 import java.io.IOException;
16 import java.net.Socket;
17
18 import org.openhab.binding.homematic.internal.common.HomematicConfig;
19 import org.openhab.binding.homematic.internal.communicator.message.BinRpcMessage;
20 import org.openhab.binding.homematic.internal.communicator.message.RpcRequest;
21 import org.openhab.binding.homematic.internal.communicator.parser.RpcResponseParser;
22 import org.openhab.binding.homematic.internal.model.HmInterface;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * Client implementation for sending messages via BIN-RPC to the Homematic server.
28  *
29  * @author Gerhard Riegler - Initial contribution
30  */
31 public class BinRpcClient extends RpcClient<byte[]> {
32     private final Logger logger = LoggerFactory.getLogger(BinRpcClient.class);
33
34     private SocketHandler socketHandler;
35
36     public BinRpcClient(HomematicConfig config) {
37         super(config);
38         socketHandler = new SocketHandler(config);
39     }
40
41     @Override
42     public void dispose() {
43         super.dispose();
44         socketHandler.flush();
45     }
46
47     @Override
48     protected RpcRequest<byte[]> createRpcRequest(String methodName) {
49         return new BinRpcMessage(methodName, config.getEncoding());
50     }
51
52     @Override
53     protected String getRpcCallbackUrl() {
54         return "binary://" + config.getCallbackHost() + ":" + config.getBinCallbackPort();
55     }
56
57     @Override
58     public void init(HmInterface hmInterface) throws IOException {
59         super.init(hmInterface);
60         socketHandler.removeSocket(config.getRpcPort(hmInterface));
61     }
62
63     /**
64      * Sends a BIN-RPC message and parses the response to see if there was an error.
65      */
66     @Override
67     protected synchronized Object[] sendMessage(int port, RpcRequest<byte[]> request) throws IOException {
68         if (logger.isTraceEnabled()) {
69             logger.trace("Client BinRpcRequest:\n{}", request);
70         }
71         return sendMessage(port, request, 0);
72     }
73
74     /**
75      * Sends the message, retries if there was an error.
76      */
77     private Object[] sendMessage(int port, RpcRequest<byte[]> request, int rpcRetryCounter) throws IOException {
78         BinRpcMessage resp = null;
79         try {
80             Socket socket = socketHandler.getSocket(port);
81             socket.getOutputStream().write(request.createMessage());
82             resp = new BinRpcMessage(socket.getInputStream(), false, config.getEncoding());
83             return new RpcResponseParser(request).parse(resp.getResponseData());
84         } catch (UnknownRpcFailureException | UnknownParameterSetException rpcEx) {
85             // throw immediately, don't retry the message
86             throw rpcEx;
87         } catch (IOException ioEx) {
88             if ("init".equals(request.getMethodName()) || rpcRetryCounter >= MAX_RPC_RETRY) {
89                 throw ioEx;
90             } else {
91                 rpcRetryCounter++;
92                 logger.debug("BinRpcMessage socket failure, sending message again {}/{}", rpcRetryCounter,
93                         MAX_RPC_RETRY);
94                 socketHandler.removeSocket(port);
95                 return sendMessage(port, request, rpcRetryCounter);
96             }
97         } finally {
98             if (logger.isTraceEnabled()) {
99                 logger.trace("Client BinRpcResponse:\n{}", resp == null ? "null" : resp.toString());
100             }
101         }
102     }
103 }