2 * Copyright (c) 2010-2020 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.homematic.internal.communicator.client;
15 import java.io.IOException;
16 import java.net.Socket;
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;
27 * Client implementation for sending messages via BIN-RPC to the Homematic server.
29 * @author Gerhard Riegler - Initial contribution
31 public class BinRpcClient extends RpcClient<byte[]> {
32 private final Logger logger = LoggerFactory.getLogger(BinRpcClient.class);
34 private SocketHandler socketHandler;
36 public BinRpcClient(HomematicConfig config) {
38 socketHandler = new SocketHandler(config);
42 public void dispose() {
43 socketHandler.flush();
47 protected RpcRequest<byte[]> createRpcRequest(String methodName) {
48 return new BinRpcMessage(methodName, config.getEncoding());
52 protected String getRpcCallbackUrl() {
53 return "binary://" + config.getCallbackHost() + ":" + config.getBinCallbackPort();
57 public void init(HmInterface hmInterface, String clientId) throws IOException {
58 super.init(hmInterface, clientId);
59 socketHandler.removeSocket(config.getRpcPort(hmInterface));
63 * Sends a BIN-RPC message and parses the response to see if there was an error.
66 protected synchronized Object[] sendMessage(int port, RpcRequest<byte[]> request) throws IOException {
67 if (logger.isTraceEnabled()) {
68 logger.trace("Client BinRpcRequest:\n{}", request);
70 return sendMessage(port, request, 0);
74 * Sends the message, retries if there was an error.
76 private Object[] sendMessage(int port, RpcRequest<byte[]> request, int rpcRetryCounter) throws IOException {
77 BinRpcMessage resp = null;
79 Socket socket = socketHandler.getSocket(port);
80 socket.getOutputStream().write(request.createMessage());
81 resp = new BinRpcMessage(socket.getInputStream(), false, config.getEncoding());
82 return new RpcResponseParser(request).parse(resp.getResponseData());
83 } catch (UnknownRpcFailureException | UnknownParameterSetException rpcEx) {
84 // throw immediately, don't retry the message
86 } catch (IOException ioEx) {
87 if ("init".equals(request.getMethodName()) || rpcRetryCounter >= MAX_RPC_RETRY) {
91 logger.debug("BinRpcMessage socket failure, sending message again {}/{}", rpcRetryCounter,
93 socketHandler.removeSocket(port);
94 return sendMessage(port, request, rpcRetryCounter);
97 if (logger.isTraceEnabled()) {
98 logger.trace("Client BinRpcResponse:\n{}", resp == null ? "null" : resp.toString());