]> git.basschouten.com Git - openhab-addons.git/blob
1eebc28fe14e01dca0cd7bd52eca81195c5343f8
[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.dsmr.internal.device.connector;
14
15 import java.io.BufferedInputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Base class for connectors. Reads data from an input stream. Subclasses should implement connection specific methods
26  * and trigger the reading of the data.
27  *
28  * @author M. Volaart - Initial contribution
29  * @author Hilbrand Bouwkamp - Major refactoring. Code moved around from other classes.
30  */
31 @NonNullByDefault
32 class DSMRBaseConnector {
33
34     private final Logger logger = LoggerFactory.getLogger(DSMRBaseConnector.class);
35
36     /**
37      * Listener to send received data and errors to.
38      */
39     protected final DSMRConnectorListener dsmrConnectorListener;
40
41     /**
42      * 1Kbyte buffer for storing received data.
43      */
44     private final byte[] buffer = new byte[1024]; // 1K
45
46     /**
47      * Read lock to have 1 process reading at a time.
48      */
49     private final Object readLock = new Object();
50
51     /**
52      * Keeps track of the open state of the connector.
53      */
54     private boolean open;
55
56     public DSMRBaseConnector(DSMRConnectorListener connectorListener) {
57         this.dsmrConnectorListener = connectorListener;
58     }
59
60     /**
61      * Input stream reading the Serial port.
62      */
63     private @Nullable BufferedInputStream inputStream;
64
65     /**
66      * Opens the connector with the given stream to read data from.
67      *
68      * @param inputStream input stream to read data from
69      * @throws IOException throws exception in case input stream is null
70      */
71     protected void open(@Nullable InputStream inputStream) throws IOException {
72         if (inputStream == null) {
73             throw new IOException("Inputstream is null");
74         }
75         this.inputStream = new BufferedInputStream(inputStream);
76         open = true;
77     }
78
79     /**
80      * @return Returns true if connector is in state open
81      */
82     protected boolean isOpen() {
83         return open;
84     }
85
86     /**
87      * Closes the connector.
88      */
89     protected void close() {
90         open = false;
91         if (inputStream != null) {
92             try {
93                 inputStream.close();
94             } catch (IOException ioe) {
95                 logger.debug("Failed to close reader", ioe);
96             }
97         }
98         inputStream = null;
99     }
100
101     /**
102      * Reads available data from the input stream.
103      */
104     protected void handleDataAvailable() {
105         try {
106             synchronized (readLock) {
107                 BufferedInputStream localInputStream = inputStream;
108
109                 if (localInputStream != null) {
110                     int bytesAvailable = localInputStream.available();
111                     while (bytesAvailable > 0) {
112                         int bytesAvailableRead = localInputStream.read(buffer, 0,
113                                 Math.min(bytesAvailable, buffer.length));
114
115                         if (open && bytesAvailableRead > 0) {
116                             dsmrConnectorListener.handleData(buffer, bytesAvailableRead);
117                         } else {
118                             logger.debug("Expected bytes {} to read, but {} bytes were read", bytesAvailable,
119                                     bytesAvailableRead);
120                         }
121                         bytesAvailable = localInputStream.available();
122                     }
123                 }
124             }
125         } catch (IOException e) {
126             dsmrConnectorListener.handleErrorEvent(DSMRConnectorErrorEvent.READ_ERROR);
127             logger.debug("Exception on read data", e);
128         }
129     }
130 }