]> git.basschouten.com Git - openhab-addons.git/blob
7b397141fc1fcaab9fdb84c1cb2ca3eb626ba5ce
[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.danfossairunit.internal;
14
15 import static org.openhab.binding.danfossairunit.internal.Commands.EMPTY;
16
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20 import java.net.InetAddress;
21 import java.net.Socket;
22 import java.util.Arrays;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * The {@link DanfossAirUnitCommunicationController} class does the actual network communication with the air unit.
31  *
32  * @author Robert Bach - initial contribution
33  * @author Jacob Laursen - Refactoring, bugfixes and enhancements
34  */
35
36 @NonNullByDefault
37 public class DanfossAirUnitCommunicationController implements CommunicationController {
38
39     private static final int SOCKET_TIMEOUT_MILLISECONDS = 5_000;
40
41     private final Logger logger = LoggerFactory.getLogger(DanfossAirUnitCommunicationController.class);
42
43     private final InetAddress inetAddr;
44     private final int port;
45     private boolean connected = false;
46     private @Nullable Socket socket;
47     private @Nullable OutputStream outputStream;
48     private @Nullable InputStream inputStream;
49
50     public DanfossAirUnitCommunicationController(InetAddress inetAddr, int port) {
51         this.inetAddr = inetAddr;
52         this.port = port;
53     }
54
55     @Override
56     public synchronized void connect() throws IOException {
57         if (connected) {
58             return;
59         }
60         Socket localSocket = new Socket(inetAddr, port);
61         localSocket.setSoTimeout(SOCKET_TIMEOUT_MILLISECONDS);
62         this.outputStream = localSocket.getOutputStream();
63         this.inputStream = localSocket.getInputStream();
64         this.socket = localSocket;
65         connected = true;
66     }
67
68     @Override
69     public synchronized void disconnect() {
70         if (!connected) {
71             return;
72         }
73         try {
74             Socket localSocket = this.socket;
75             if (localSocket != null) {
76                 localSocket.close();
77             }
78         } catch (IOException ioe) {
79             logger.debug("Connection to air unit could not be closed gracefully. {}", ioe.getMessage());
80         } finally {
81             this.socket = null;
82             this.inputStream = null;
83             this.outputStream = null;
84         }
85         connected = false;
86     }
87
88     @Override
89     public byte[] sendRobustRequest(byte[] operation, byte[] register) throws IOException {
90         return sendRobustRequest(operation, register, EMPTY);
91     }
92
93     @Override
94     public synchronized byte[] sendRobustRequest(byte[] operation, byte[] register, byte[] value) throws IOException {
95         connect();
96         byte[] request = new byte[4 + value.length];
97         System.arraycopy(operation, 0, request, 0, 2);
98         System.arraycopy(register, 0, request, 2, 2);
99         System.arraycopy(value, 0, request, 4, value.length);
100         try {
101             return sendRequestInternal(request);
102         } catch (IOException ioe) {
103             // retry once if there was connection problem
104             disconnect();
105             connect();
106             return sendRequestInternal(request);
107         }
108     }
109
110     private synchronized byte[] sendRequestInternal(byte[] request) throws IOException {
111         OutputStream localOutputStream = this.outputStream;
112
113         if (localOutputStream == null) {
114             throw new IOException(
115                     String.format("Output stream is null while sending request: %s", Arrays.toString(request)));
116         }
117         localOutputStream.write(request);
118         localOutputStream.flush();
119
120         byte[] result = new byte[63];
121         InputStream localInputStream = this.inputStream;
122         if (localInputStream == null) {
123             throw new IOException(
124                     String.format("Input stream is null while sending request: %s", Arrays.toString(request)));
125         }
126
127         int bytesRead = localInputStream.read(result, 0, 63);
128         if (bytesRead < 63) {
129             throw new IOException(String.format(
130                     "Error reading from stream, read returned %d as number of bytes read into the buffer", bytesRead));
131         }
132
133         return result;
134     }
135 }