2 * Copyright (c) 2010-2023 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.dsmr.internal.device.connector;
15 import java.io.BufferedInputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.util.Optional;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Base class for connectors. Reads data from an input stream. Subclasses should implement connection specific methods
27 * and trigger the reading of the data.
29 * @author M. Volaart - Initial contribution
30 * @author Hilbrand Bouwkamp - Major refactoring. Code moved around from other classes.
33 class DSMRBaseConnector {
35 private final Logger logger = LoggerFactory.getLogger(DSMRBaseConnector.class);
38 * Listener to send received data and errors to.
40 private final DSMRConnectorListener dsmrConnectorListener;
43 * 1Kbyte buffer for storing received data.
45 private final byte[] buffer = new byte[1024]; // 1K
48 * Read lock to have 1 process reading at a time.
50 private final Object readLock = new Object();
53 * Keeps track of the open state of the connector.
57 public DSMRBaseConnector(final DSMRConnectorListener connectorListener) {
58 this.dsmrConnectorListener = connectorListener;
62 * Input stream reading the Serial port.
64 private @Nullable BufferedInputStream inputStream;
67 * Opens the connector with the given stream to read data from.
69 * @param inputStream input stream to read data from
70 * @throws IOException throws exception in case input stream is null
72 protected void open(@Nullable final InputStream inputStream) throws IOException {
73 if (inputStream == null) {
74 throw new IOException("Inputstream is null");
76 this.inputStream = new BufferedInputStream(inputStream);
81 * @return Returns true if connector is in state open
83 protected boolean isOpen() {
88 * Closes the connector.
90 protected void close() {
92 if (inputStream != null) {
95 } catch (final IOException ioe) {
96 logger.debug("Failed to close reader", ioe);
103 * Reads available data from the input stream.
105 protected void handleDataAvailable() {
107 synchronized (readLock) {
108 final BufferedInputStream localInputStream = inputStream;
110 if (localInputStream != null) {
111 int bytesAvailable = localInputStream.available();
112 while (bytesAvailable > 0) {
113 final int bytesAvailableRead = localInputStream.read(buffer, 0,
114 Math.min(bytesAvailable, buffer.length));
116 if (open && bytesAvailableRead > 0) {
117 dsmrConnectorListener.handleData(buffer, bytesAvailableRead);
119 logger.debug("Expected bytes {} to read, but {} bytes were read", bytesAvailable,
122 bytesAvailable = localInputStream.available();
126 } catch (final IOException e) {
127 dsmrConnectorListener.handleError(DSMRErrorStatus.SERIAL_DATA_READ_ERROR,
128 Optional.ofNullable(e.getMessage()).orElse(""));
129 logger.debug("Exception on read data", e);