]> git.basschouten.com Git - openhab-addons.git/blob
281ae670dbf4caed21ec0edfaabcafe7342ab5cd
[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.luxtronikheatpump.internal;
14
15 import java.io.DataInputStream;
16 import java.io.DataOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20 import java.net.Socket;
21 import java.net.UnknownHostException;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * The {@link HeatpumpConnector} reads / writes internal states of a Heat pump with Luxtronik control.
29  *
30  * Based on HeatpumpConnector class of novelanheatpump binding
31  * 
32  * @author Stefan Giehl - Initial contribution
33  */
34 @NonNullByDefault
35 public class HeatpumpConnector {
36
37     private static final int SOCKET_PARAM_WRITE_PARAMS = 3002;
38     private static final int SOCKET_PARAM_READ_PARAMS = 3003;
39     private static final int SOCKET_PARAM_READ_VALUES = 3004;
40     private static final int SOCKET_PARAM_READ_VISIBILITIES = 3005;
41
42     private final Logger logger = LoggerFactory.getLogger(HeatpumpConnector.class);
43
44     private String serverIp;
45     private int serverPort;
46     private Integer[] heatpumpValues = new Integer[0];
47     private Integer[] heatpumpParams = new Integer[0];
48     private Integer[] heatpumpVisibilities = new Integer[0];
49
50     public HeatpumpConnector(String serverIp, int serverPort) {
51         this.serverIp = serverIp;
52         this.serverPort = serverPort;
53     }
54
55     /**
56      * reads all values from the heatpump via network
57      * 
58      * @throws UnknownHostException indicate that the IP address of a host could not be determined.
59      * @throws IOException indicate that no data can be read from the heat pump
60      */
61     public void read() throws UnknownHostException, IOException {
62         try (Socket sock = new Socket(serverIp, serverPort)) {
63             InputStream in = sock.getInputStream();
64             OutputStream out = sock.getOutputStream();
65             DataInputStream datain = new DataInputStream(in);
66             DataOutputStream dataout = new DataOutputStream(out);
67
68             heatpumpValues = readInt(datain, dataout, SOCKET_PARAM_READ_VALUES);
69
70             // workaround for thermal energies
71             // the thermal energies can be unreasonably high in some cases, probably due to a sign bug in the firmware
72             // trying to correct this issue here
73             for (int i = 151; i <= 154; i++) {
74                 if (heatpumpValues.length > i && heatpumpValues[i] >= 214748364) {
75                     heatpumpValues[i] -= 214748364;
76                 }
77             }
78
79             heatpumpParams = readInt(datain, dataout, SOCKET_PARAM_READ_PARAMS);
80             heatpumpVisibilities = readInt(datain, dataout, SOCKET_PARAM_READ_VISIBILITIES);
81
82             datain.close();
83             dataout.close();
84         }
85     }
86
87     /**
88      * read the parameters of the heat pump
89      */
90     public Integer[] getParams() {
91         return heatpumpParams;
92     }
93
94     /**
95      * set a parameter of the heat pump
96      * 
97      * @param param
98      * @param value
99      * @throws IOException indicate that no data can be sent to the heat pump
100      */
101     public boolean setParam(int param, int value) throws IOException {
102         try (Socket sock = new Socket(serverIp, serverPort)) {
103             InputStream in = sock.getInputStream();
104             OutputStream out = sock.getOutputStream();
105             DataInputStream datain = new DataInputStream(in);
106             DataOutputStream dataout = new DataOutputStream(out);
107
108             while (datain.available() > 0) {
109                 datain.readByte();
110             }
111
112             // write command, param and value to heatpump socket
113             dataout.writeInt(SOCKET_PARAM_WRITE_PARAMS);
114             dataout.writeInt(param);
115             dataout.writeInt(value);
116             dataout.flush();
117
118             // first integer on socket output should represent the command
119             int cmd = datain.readInt();
120             datain.readInt();
121
122             datain.close();
123             dataout.close();
124
125             if (cmd != SOCKET_PARAM_WRITE_PARAMS) {
126                 logger.debug("Couldn't write parameter {} with value {} to heat pump.", param, value);
127                 return false;
128             } else {
129                 logger.debug("Parameter {} with value {} successfully written to heat pump.", param, value);
130                 return true;
131             }
132         }
133     }
134
135     /**
136      * Returns the internal states of the heat pump
137      * 
138      * @return an array with all internal data of the heat pump
139      */
140     public Integer[] getValues() {
141         return heatpumpValues;
142     }
143
144     /**
145      * Returns the internal visibilities of the heat pump
146      *
147      * @return an array with all internal visibilities of the heat pump
148      */
149     public Integer[] getVisibilities() {
150         return heatpumpVisibilities;
151     }
152
153     /**
154      * Reads all available values for the given parameter from socket
155      * 
156      * @param datain data input stream of socket connection
157      * @param dataout data output stream of socket connection
158      * @param parameter int command to read from socket
159      * @return an array with all values returned from heat pump socket
160      * @throws IOException indicate that no data can be read from the heat pump
161      */
162     private Integer[] readInt(DataInputStream datain, DataOutputStream dataout, int parameter) throws IOException {
163         Integer[] result = null;
164         while (datain.available() > 0) {
165             datain.readByte();
166         }
167
168         // to receive values we first need to write the command followed by four 0 byte values to the socket
169         dataout.writeInt(parameter);
170         dataout.writeInt(0);
171         dataout.flush();
172
173         // the first integer received from socket should match the written command
174         if (datain.readInt() != parameter) {
175             return new Integer[0];
176         }
177
178         if (parameter == SOCKET_PARAM_READ_VALUES) {
179             // when reading values the next integer represents some kind of status
180             datain.readInt();
181         }
182
183         // the next integer value should define the number of values that are following
184         // Currently the list or parameters is the longest list and contains around 1050 values
185         // To avoid possible (memory) problems in case the returned number would be unexpected high we limit it to 2000
186         int arraylength = Integer.min(datain.readInt(), 2000);
187
188         logger.debug("Found {} values for {}", arraylength, parameter);
189
190         result = new Integer[arraylength];
191
192         // Note: the visibility params are returned as single byte values
193         // probably as the are used as boolean values (0/1) only
194         if (parameter == SOCKET_PARAM_READ_VISIBILITIES) {
195             byte[] data = datain.readNBytes(arraylength);
196             for (int i = 0; i < data.length; i++) {
197                 result[i] = (int) data[i];
198             }
199             return result;
200         }
201
202         for (int i = 0; i < arraylength; i++) {
203             result[i] = datain.readInt();
204         }
205
206         return result;
207     }
208 }