If for some reason HP response fails to properly parse, i.e. java.lang.NumberFormatException: For input string: "##" exception is not handled and scheduler is not re-triggered (polling stops).Fixed build warnings. (#13685)

Signed-off-by: Boris Krivonog <boris.krivonog@inova.si>
This commit is contained in:
Boris Krivonog 2022-11-12 10:44:45 +01:00 committed by GitHub
parent fe269b127a
commit 248ca1830a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 191 additions and 54 deletions

View File

@ -26,6 +26,8 @@ import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.regoheatpump.internal.protocol.RegoConnection;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
@ -34,6 +36,7 @@ import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
@ -45,13 +48,14 @@ import org.slf4j.LoggerFactory;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
abstract class HusdataHandler extends BaseThingHandler {
private static final Map<Integer, String> MAPPINGS;
private final Logger logger = LoggerFactory.getLogger(HusdataHandler.class);
private RegoConnection connection;
private ScheduledFuture<?> scheduledRefreshFuture;
private BufferedReader bufferedReader;
private @Nullable RegoConnection connection;
private @Nullable ScheduledFuture<?> scheduledRefreshFuture;
private @Nullable BufferedReader bufferedReader;
static {
MAPPINGS = mappings();
@ -61,12 +65,18 @@ abstract class HusdataHandler extends BaseThingHandler {
super(thing);
}
protected abstract RegoConnection createConnection();
protected abstract RegoConnection createConnection() throws IOException;
@Override
public void initialize() {
bufferedReader = null;
try {
connection = createConnection();
} catch (IOException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
return;
}
updateStatus(ThingStatus.UNKNOWN);
@ -78,14 +88,16 @@ abstract class HusdataHandler extends BaseThingHandler {
public void dispose() {
super.dispose();
ScheduledFuture<?> scheduledRefreshFuture = this.scheduledRefreshFuture;
this.scheduledRefreshFuture = null;
if (scheduledRefreshFuture != null) {
scheduledRefreshFuture.cancel(true);
scheduledRefreshFuture = null;
}
RegoConnection connection = this.connection;
this.connection = null;
if (connection != null) {
connection.close();
connection = null;
}
}
@ -112,8 +124,10 @@ abstract class HusdataHandler extends BaseThingHandler {
outputStream.flush();
}
BufferedReader bufferedReader = this.bufferedReader;
if (bufferedReader == null) {
bufferedReader = new BufferedReader(new InputStreamReader(connection.inputStream()));
this.bufferedReader = bufferedReader;
}
final String line = bufferedReader.readLine();

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.regoheatpump.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.regoheatpump.internal.RegoHeatPumpBindingConstants;
import org.openhab.binding.regoheatpump.internal.protocol.IpRegoConnection;
import org.openhab.binding.regoheatpump.internal.protocol.RegoConnection;
@ -23,6 +24,7 @@ import org.openhab.core.thing.Thing;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class IpHusdataHandler extends HusdataHandler {
public IpHusdataHandler(Thing thing) {
super(thing);

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.regoheatpump.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.regoheatpump.internal.RegoHeatPumpBindingConstants;
import org.openhab.binding.regoheatpump.internal.protocol.IpRegoConnection;
import org.openhab.binding.regoheatpump.internal.protocol.RegoConnection;
@ -23,6 +24,7 @@ import org.openhab.core.thing.Thing;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class IpRego6xxHeatPumpHandler extends Rego6xxHeatPumpHandler {
public IpRego6xxHeatPumpHandler(Thing thing) {
super(thing);

View File

@ -29,6 +29,8 @@ import java.util.stream.Collectors;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.regoheatpump.internal.protocol.RegoConnection;
import org.openhab.binding.regoheatpump.internal.rego6xx.CommandFactory;
import org.openhab.binding.regoheatpump.internal.rego6xx.ErrorLine;
@ -60,13 +62,15 @@ import org.slf4j.LoggerFactory;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
private static final class ChannelDescriptor {
private Date lastUpdate;
private byte[] cachedValue;
private @Nullable Date lastUpdate;
private byte @Nullable [] cachedValue;
public byte[] cachedValueIfNotExpired(int refreshTime) {
public byte @Nullable [] cachedValueIfNotExpired(int refreshTime) {
Date lastUpdate = this.lastUpdate;
if (lastUpdate == null || (lastUpdate.getTime() + refreshTime * 900 < new Date().getTime())) {
return null;
}
@ -82,23 +86,27 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(Rego6xxHeatPumpHandler.class);
private final Map<String, ChannelDescriptor> channelDescriptors = new HashMap<>();
private final RegoRegisterMapper mapper = RegoRegisterMapper.REGO600;
private @Nullable RegoConnection connection;
private @Nullable ScheduledFuture<?> scheduledRefreshFuture;
private int refreshInterval;
private RegoConnection connection;
private RegoRegisterMapper mapper;
private ScheduledFuture<?> scheduledRefreshFuture;
protected Rego6xxHeatPumpHandler(Thing thing) {
super(thing);
}
protected abstract RegoConnection createConnection();
protected abstract RegoConnection createConnection() throws IOException;
@Override
public void initialize() {
mapper = RegoRegisterMapper.REGO600;
refreshInterval = ((Number) getConfig().get(REFRESH_INTERVAL)).intValue();
try {
connection = createConnection();
} catch (IOException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
return;
}
scheduledRefreshFuture = scheduler.scheduleWithFixedDelay(this::refresh, 2, refreshInterval, TimeUnit.SECONDS);
@ -109,21 +117,21 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
public void dispose() {
super.dispose();
RegoConnection connection = this.connection;
this.connection = null;
if (connection != null) {
connection.close();
}
ScheduledFuture<?> scheduledRefreshFuture = this.scheduledRefreshFuture;
this.scheduledRefreshFuture = null;
if (scheduledRefreshFuture != null) {
scheduledRefreshFuture.cancel(true);
scheduledRefreshFuture = null;
}
synchronized (channelDescriptors) {
channelDescriptors.clear();
}
connection = null;
mapper = null;
}
@Override
@ -220,7 +228,7 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
private void readAndUpdateLastError(String channelIID, Function<ErrorLine, State> converter) {
executeCommandAndUpdateState(channelIID, CommandFactory.createReadLastErrorCommand(),
ResponseParserFactory.ERROR_LINE, e -> {
return e == null ? UnDefType.NULL : converter.apply(e);
return e == ErrorLine.NO_ERROR ? UnDefType.NULL : converter.apply(e);
});
}
@ -252,7 +260,7 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
});
}
private synchronized <T> void executeCommand(String channelIID, byte[] command, ResponseParser<T> parser,
private synchronized <T> void executeCommand(@Nullable String channelIID, byte[] command, ResponseParser<T> parser,
Consumer<T> resultProcessor) {
try {
T result = executeCommandWithRetry(channelIID, command, parser, 5);
@ -265,17 +273,19 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
}
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
} catch (Rego6xxProtocolException e) {
} catch (Rego6xxProtocolException | RuntimeException e) {
logger.warn("Executing command for channel '{}' failed.", channelIID, e);
if (channelIID != null) {
updateState(channelIID, UnDefType.UNDEF);
}
} catch (InterruptedException e) {
logger.debug("Execution interrupted when accessing value for channel '{}'.", channelIID, e);
Thread.currentThread().interrupt();
}
}
private <T> T executeCommandWithRetry(String channelIID, byte[] command, ResponseParser<T> parser, int retry)
throws Rego6xxProtocolException, IOException, InterruptedException {
private <T> T executeCommandWithRetry(@Nullable String channelIID, byte[] command, ResponseParser<T> parser,
int retry) throws Rego6xxProtocolException, IOException, InterruptedException {
try {
checkRegoDevice();
return executeCommand(channelIID, command, parser);
@ -316,11 +326,12 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
}
}
private <T> T executeCommand(String channelIID, byte[] command, ResponseParser<T> parser)
private <T> T executeCommand(@Nullable String channelIID, byte[] command, ResponseParser<T> parser)
throws Rego6xxProtocolException, IOException, InterruptedException {
try {
return executeCommandInternal(channelIID, command, parser);
} catch (IOException e) {
RegoConnection connection = this.connection;
if (connection != null) {
connection.close();
}
@ -329,7 +340,7 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
}
}
private <T> T executeCommandInternal(String channelIID, byte[] command, ResponseParser<T> parser)
private <T> T executeCommandInternal(@Nullable String channelIID, byte[] command, ResponseParser<T> parser)
throws Rego6xxProtocolException, IOException, InterruptedException {
// CHANNEL_LAST_ERROR_CODE and CHANNEL_LAST_ERROR_TIMESTAMP are read from same
// register. To prevent accessing same register twice when both channels are linked,
@ -338,8 +349,12 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
|| CHANNEL_LAST_ERROR_TIMESTAMP.equals(channelIID)) ? CHANNEL_LAST_ERROR : channelIID;
// Use transient channel descriptor for null (not cached) channels.
ChannelDescriptor descriptor = channelIID == null ? new ChannelDescriptor()
: channelDescriptorForChannel(mappedChannelIID);
ChannelDescriptor descriptor;
if (mappedChannelIID == null) {
descriptor = new ChannelDescriptor();
} else {
descriptor = channelDescriptorForChannel(mappedChannelIID);
}
byte[] cachedValue = descriptor.cachedValueIfNotExpired(refreshInterval);
if (cachedValue != null) {
@ -348,6 +363,11 @@ abstract class Rego6xxHeatPumpHandler extends BaseThingHandler {
}
// Send command to device and wait for response.
RegoConnection connection = this.connection;
if (connection == null) {
throw new IOException("Unable to execute command - no connection available");
}
if (!connection.isConnected()) {
connection.connect();
}

View File

@ -12,6 +12,10 @@
*/
package org.openhab.binding.regoheatpump.internal.handler;
import java.io.IOException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.regoheatpump.internal.RegoHeatPumpBindingConstants;
import org.openhab.binding.regoheatpump.internal.protocol.RegoConnection;
import org.openhab.binding.regoheatpump.internal.protocol.SerialRegoConnection;
@ -27,9 +31,10 @@ import org.openhab.core.thing.ThingStatusDetail;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class SerialHusdataHandler extends HusdataHandler {
private final SerialPortManager serialPortManager;
private SerialPortIdentifier serialPortIdentifier;
private @Nullable SerialPortIdentifier serialPortIdentifier;
public SerialHusdataHandler(Thing thing, SerialPortManager serialPortManager) {
super(thing);
@ -49,7 +54,11 @@ public class SerialHusdataHandler extends HusdataHandler {
}
@Override
protected RegoConnection createConnection() {
protected RegoConnection createConnection() throws IOException {
SerialPortIdentifier serialPortIdentifier = this.serialPortIdentifier;
if (serialPortIdentifier == null) {
throw new IOException("Serial port does not exist");
}
return new SerialRegoConnection(serialPortIdentifier, 19200);
}
}

View File

@ -12,6 +12,10 @@
*/
package org.openhab.binding.regoheatpump.internal.handler;
import java.io.IOException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.regoheatpump.internal.RegoHeatPumpBindingConstants;
import org.openhab.binding.regoheatpump.internal.protocol.RegoConnection;
import org.openhab.binding.regoheatpump.internal.protocol.SerialRegoConnection;
@ -27,9 +31,10 @@ import org.openhab.core.thing.ThingStatusDetail;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class SerialRego6xxHeatPumpHandler extends Rego6xxHeatPumpHandler {
private final SerialPortManager serialPortManager;
private SerialPortIdentifier serialPortIdentifier;
private @Nullable SerialPortIdentifier serialPortIdentifier;
public SerialRego6xxHeatPumpHandler(Thing thing, SerialPortManager serialPortManager) {
super(thing);
@ -49,7 +54,11 @@ public class SerialRego6xxHeatPumpHandler extends Rego6xxHeatPumpHandler {
}
@Override
protected RegoConnection createConnection() {
protected RegoConnection createConnection() throws IOException {
SerialPortIdentifier serialPortIdentifier = this.serialPortIdentifier;
if (serialPortIdentifier == null) {
throw new IOException("Serial port does not exist");
}
return new SerialRegoConnection(serialPortIdentifier, 19200);
}
}

View File

@ -18,6 +18,8 @@ import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -26,6 +28,7 @@ import org.slf4j.LoggerFactory;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class IpRegoConnection implements RegoConnection {
/**
* Connection timeout in milliseconds
@ -40,7 +43,7 @@ public class IpRegoConnection implements RegoConnection {
private final Logger logger = LoggerFactory.getLogger(IpRegoConnection.class);
private final String address;
private final int port;
private Socket clientSocket;
private @Nullable Socket clientSocket;
public IpRegoConnection(String address, int port) {
this.address = address;
@ -50,10 +53,12 @@ public class IpRegoConnection implements RegoConnection {
@Override
public void connect() throws IOException {
logger.debug("Connecting to '{}', port = {}.", address, port);
Socket clientSocket = this.clientSocket;
if (clientSocket == null) {
clientSocket = new Socket();
clientSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
clientSocket.setKeepAlive(true);
this.clientSocket = clientSocket;
}
clientSocket.connect(new InetSocketAddress(address, port), CONNECTION_TIMEOUT);
logger.debug("Connected to '{}', port = {}.", address, port);
@ -61,12 +66,15 @@ public class IpRegoConnection implements RegoConnection {
@Override
public boolean isConnected() {
Socket clientSocket = this.clientSocket;
return clientSocket != null && clientSocket.isConnected();
}
@Override
public void close() {
try {
Socket clientSocket = this.clientSocket;
this.clientSocket = null;
if (clientSocket != null) {
clientSocket.close();
}
@ -74,17 +82,23 @@ public class IpRegoConnection implements RegoConnection {
// There is really not much we can do here, ignore the error and continue execution.
logger.warn("Closing socket failed", e);
}
clientSocket = null;
}
@Override
public OutputStream outputStream() throws IOException {
return clientSocket.getOutputStream();
return getClientSocket().getOutputStream();
}
@Override
public InputStream inputStream() throws IOException {
return clientSocket.getInputStream();
return getClientSocket().getInputStream();
}
private Socket getClientSocket() throws IOException {
Socket clientSocket = this.clientSocket;
if (clientSocket == null) {
throw new IOException("Socket closed");
}
return clientSocket;
}
}

View File

@ -16,11 +16,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link RegoConnection} is responsible for creating connections to clients.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public interface RegoConnection {
/**
* Connect to the receiver. Return true if the connection has succeeded or if already connected.

View File

@ -16,6 +16,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.io.transport.serial.PortInUseException;
import org.openhab.core.io.transport.serial.SerialPort;
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
@ -26,10 +28,11 @@ import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class SerialRegoConnection implements RegoConnection {
private final int baudRate;
private final String portName;
private SerialPort serialPort;
private @Nullable SerialPort serialPort;
private final SerialPortIdentifier serialPortIdentifier;
public SerialRegoConnection(SerialPortIdentifier serialPortIdentifier, int baudRate) {
@ -41,10 +44,11 @@ public class SerialRegoConnection implements RegoConnection {
@Override
public void connect() throws IOException {
try {
serialPort = serialPortIdentifier.open(SerialRegoConnection.class.getCanonicalName(), 2000);
SerialPort serialPort = serialPortIdentifier.open(SerialRegoConnection.class.getCanonicalName(), 2000);
serialPort.enableReceiveTimeout(100);
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
this.serialPort = serialPort;
} catch (PortInUseException e) {
throw new IOException("Serial port already used: " + portName, e);
} catch (UnsupportedCommOperationException e) {
@ -59,19 +63,36 @@ public class SerialRegoConnection implements RegoConnection {
@Override
public void close() {
SerialPort serialPort = this.serialPort;
this.serialPort = null;
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
}
@Override
public OutputStream outputStream() throws IOException {
return serialPort.getOutputStream();
OutputStream outputStream = getSerialPort().getOutputStream();
if (outputStream == null) {
throw new IOException("Sending data is not supported");
}
return outputStream;
}
@Override
public InputStream inputStream() throws IOException {
return serialPort.getInputStream();
InputStream inputStream = getSerialPort().getInputStream();
if (inputStream == null) {
throw new IOException("Receiving data is not supported");
}
return inputStream;
}
private SerialPort getSerialPort() throws IOException {
SerialPort serialPort = this.serialPort;
if (serialPort == null) {
throw new IOException("Connection closed");
}
return serialPort;
}
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link AbstractLongResponseParser} is responsible for parsing long form responses.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
abstract class AbstractLongResponseParser<T> extends AbstractResponseParser<T> {
@Override
public int responseLength() {

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.util.HexUtils;
/**
@ -20,6 +21,7 @@ import org.openhab.core.util.HexUtils;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
abstract class AbstractResponseParser<T> implements ResponseParser<T> {
private static final byte COMPUTER_ADDRESS = (byte) 0x01;

View File

@ -14,11 +14,14 @@ package org.openhab.binding.regoheatpump.internal.rego6xx;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link Checksum} is responsible for calculating checksum of given data.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
class Checksum {
static byte calculate(byte[]... lists) {
return Arrays.stream(lists).reduce((byte) 0, Checksum::calculate, (a, b) -> b);

View File

@ -12,12 +12,15 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link CommandFactory} is responsible for creating different commands that can
* be send to a rego 6xx unit.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class CommandFactory {
private static final byte DEVICE_ADDRESS = (byte) 0x81;

View File

@ -15,15 +15,20 @@ package org.openhab.binding.regoheatpump.internal.rego6xx;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link ErrorLine} is responsible for holding information about a single error line.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class ErrorLine {
private final byte error;
private final String timestamp;
public static final ErrorLine NO_ERROR = new ErrorLine((byte) 0, "");
public ErrorLine(byte error, String timestamp) {
this.error = error;
this.timestamp = timestamp;

View File

@ -12,18 +12,21 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link ErrorLineResponseParser} is responsible for parsing error information (log) entry.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
class ErrorLineResponseParser extends AbstractLongResponseParser<ErrorLine> {
@Override
protected ErrorLine convert(byte[] responseBytes) {
// 255 marks no error.
if (responseBytes[1] == (byte) 255) {
return null;
return ErrorLine.NO_ERROR;
}
return new ErrorLine(ValueConverter.arrayToByte(responseBytes, 1),

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link Rego6xxProtocolException} is responsible for holding information about an Rego6xx protocol error.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class Rego6xxProtocolException extends Exception {
private static final long serialVersionUID = 7556083982084149686L;

View File

@ -19,6 +19,8 @@ import java.util.Map;
import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
@ -27,6 +29,7 @@ import org.openhab.core.library.unit.Units;
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class RegoRegisterMapper {
public static final RegoRegisterMapper REGO600;
@ -35,7 +38,7 @@ public class RegoRegisterMapper {
public double scaleFactor();
public Unit<?> unit();
public @Nullable Unit<?> unit();
public int convertValue(short value);
}
@ -44,9 +47,9 @@ public class RegoRegisterMapper {
private static class ChannelImpl implements Channel {
private final short address;
private final double scaleFactor;
private final Unit<?> unit;
private @Nullable final Unit<?> unit;
private ChannelImpl(short address, double scaleFactor, Unit<?> unit) {
private ChannelImpl(short address, double scaleFactor, @Nullable Unit<?> unit) {
this.address = address;
this.scaleFactor = scaleFactor;
this.unit = unit;
@ -63,7 +66,7 @@ public class RegoRegisterMapper {
}
@Override
public Unit<?> unit() {
public @Nullable Unit<?> unit() {
return unit;
}
@ -104,7 +107,7 @@ public class RegoRegisterMapper {
this.mappings = mappings;
}
public Channel map(String channelIID) {
public @Nullable Channel map(String channelIID) {
return mappings.get(channelIID);
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link ResponseParser} is responsible for parsing arbitrary data coming from a rego 6xx unit.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public interface ResponseParser<T> {
public int responseLength();

View File

@ -12,15 +12,18 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link ResponseParserFactory} is responsible for providing parsers for all known data
* forms coming from the rego 6xx unit.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
public class ResponseParserFactory {
public static final ResponseParser<Short> SHORT = new ShortResponseParser();
public static final ResponseParser<String> STRING = new StringResponseParser();
public static final ResponseParser<ErrorLine> ERROR_LINE = new ErrorLineResponseParser();
public static final ResponseParser<Void> WRITE = new WriteResponse();
public static final ResponseParser<String> WRITE = new WriteResponse();
}

View File

@ -12,12 +12,15 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link ShortResponseParser} is responsible for parsing short form data format
* coming from the rego 6xx unit.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
class ShortResponseParser extends AbstractResponseParser<Short> {
@Override

View File

@ -12,12 +12,15 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link StringResponseParser} is responsible for parsing long (text) form data format
* coming from the rego 6xx unit.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
class StringResponseParser extends AbstractLongResponseParser<String> {
@Override

View File

@ -12,11 +12,14 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link ValueConverter} is responsible for converting various rego 6xx specific data types.
*
* @author Boris Krivonog - Initial contribution
*/
@NonNullByDefault
class ValueConverter {
public static byte[] shortToSevenBitFormat(short value) {
byte b1 = (byte) ((value & 0xC000) >> 14);

View File

@ -12,20 +12,23 @@
*/
package org.openhab.binding.regoheatpump.internal.rego6xx;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link WriteResponse} is responsible for parsing write responses
* coming from the rego 6xx unit.
*
* @author Boris Krivonog - Initial contribution
*/
class WriteResponse extends AbstractResponseParser<Void> {
@NonNullByDefault
class WriteResponse extends AbstractResponseParser<String> {
@Override
public int responseLength() {
return 1;
}
@Override
protected Void convert(byte[] responseBytes) {
return null;
protected String convert(byte[] responseBytes) {
return "";
}
}