[modbus] Moved modbus transport from addons to core (#9268)
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
parent
1a6f5b5158
commit
f152a58a31
bundles
org.openhab.binding.modbus.e3dc
pom.xml
src
main
feature
java/org/openhab/binding/modbus/e3dc/internal
test/java/org/openhab/binding/modbus/e3dc
org.openhab.binding.modbus.helioseasycontrols
pom.xml
src
main
feature
java/org/openhab/binding/modbus/helioseasycontrols/internal
test/java/org/openhab/binding/modbus/helioseasycontrols/internal
org.openhab.binding.modbus.stiebeleltron
org.openhab.binding.modbus.studer
org.openhab.binding.modbus.sunspec
org.openhab.binding.modbus
org.openhab.io.transport.modbus
NOTICEREADME.mdpom.xml
src/main
feature
java/org/openhab/io/transport/modbus
AsyncModbusFailure.javaAsyncModbusReadResult.javaAsyncModbusWriteResult.javaBitArray.javaModbusBitUtilities.javaModbusCommunicationInterface.javaModbusConstants.javaModbusFailureCallback.javaModbusManager.javaModbusReadCallback.javaModbusReadFunctionCode.javaModbusReadRequestBlueprint.javaModbusRegisterArray.javaModbusResponse.javaModbusResultCallback.javaModbusWriteCallback.javaModbusWriteCoilRequestBlueprint.javaModbusWriteFunctionCode.javaModbusWriteRegisterRequestBlueprint.javaModbusWriteRequestBlueprint.javaModbusWriteRequestBlueprintVisitor.javaPollTask.javaTaskWithEndpoint.javaValueBuffer.javaWriteTask.java
endpoint
EndpointPoolConfiguration.javaModbusIPSlaveEndpoint.javaModbusSerialSlaveEndpoint.javaModbusSlaveEndpoint.javaModbusSlaveEndpointVisitor.javaModbusTCPSlaveEndpoint.javaModbusUDPSlaveEndpoint.java
exception
ModbusConnectionException.javaModbusSlaveErrorResponseException.javaModbusSlaveIOException.javaModbusTransportException.javaModbusUnexpectedResponseFunctionCodeException.javaModbusUnexpectedResponseSizeException.javaModbusUnexpectedTransactionIdException.java
internal
@ -21,11 +21,5 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.e3dc-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus-e3dc" description="E3DC Modbus Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.e3dc/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -16,8 +16,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link DataConverter} Helper class to convert bytes from modbus into desired data format
|
||||
|
@ -18,9 +18,9 @@ import java.util.BitSet;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
|
||||
/**
|
||||
* The {@link EmergencyBlock} Data object for E3DC Info Block
|
||||
|
@ -14,10 +14,10 @@ package org.openhab.binding.modbus.e3dc.internal.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link InfoBlock} Data object for E3DC Info Block
|
||||
|
@ -17,9 +17,9 @@ import javax.measure.quantity.Power;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link PowerBlock} Data object for E3DC Info Block
|
||||
|
@ -18,9 +18,9 @@ import javax.measure.quantity.Power;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link StringBlock} Data object for E3DC Info Block
|
||||
|
@ -30,6 +30,12 @@ import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -38,12 +44,6 @@ import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -28,6 +28,12 @@ import org.openhab.binding.modbus.e3dc.internal.dto.WallboxBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Parser;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -37,12 +43,6 @@ import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -24,8 +24,8 @@ import org.openhab.binding.modbus.e3dc.internal.dto.PowerBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.StringBlock;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.WallboxArray;
|
||||
import org.openhab.binding.modbus.e3dc.internal.modbus.Data.DataType;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -20,6 +20,10 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
@ -27,10 +31,6 @@ import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* The {@link E3DCHandlerStateTest} Test State handling of Handler if different results occurs
|
||||
|
@ -19,7 +19,7 @@ import java.util.BitSet;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.modbus.e3dc.internal.dto.DataConverter;
|
||||
import org.openhab.io.transport.modbus.ValueBuffer;
|
||||
import org.openhab.core.io.transport.modbus.ValueBuffer;
|
||||
|
||||
/**
|
||||
* The {@link DataConverterTest} Test data conversions
|
||||
|
@ -15,12 +15,6 @@
|
||||
<name>openHAB Add-ons :: Bundles :: HeliosEasyControls Binding</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.modbus</artifactId>
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.helioseasycontrols-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus-helioseasycontrols" description="Modbus.HeliosEasyControls Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.helioseasycontrols/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -31,6 +31,13 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
@ -50,13 +57,6 @@ import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -23,7 +23,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* @author Sami Salonen - Initial contribution
|
||||
|
@ -21,12 +21,6 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.stiebeleltron-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus-stiebeleltron" description="StiebelEltron Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.stiebeleltron/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -33,6 +33,14 @@ import org.openhab.binding.modbus.stiebeleltron.internal.parser.EnergyBlockParse
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemInfromationBlockParser;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemParameterBlockParser;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.parser.SystemStateBlockParser;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
@ -47,14 +55,6 @@ import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -15,10 +15,10 @@ package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Base class for parsers with some helper methods
|
||||
|
@ -14,7 +14,7 @@ package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.EnergyBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an Energy Block
|
||||
|
@ -14,7 +14,7 @@ package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemInformationBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an SystemB Information lock
|
||||
|
@ -14,7 +14,7 @@ package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemParameterBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an System Parameter Block
|
||||
|
@ -14,7 +14,7 @@ package org.openhab.binding.modbus.stiebeleltron.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.stiebeleltron.internal.dto.SystemStateBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an System State Block
|
||||
|
@ -20,11 +20,5 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.studer-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus-studer" description="Studer Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.studer/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -27,6 +27,14 @@ import org.openhab.binding.modbus.studer.internal.StuderParser.ModeXtender;
|
||||
import org.openhab.binding.modbus.studer.internal.StuderParser.VSMode;
|
||||
import org.openhab.binding.modbus.studer.internal.StuderParser.VTMode;
|
||||
import org.openhab.binding.modbus.studer.internal.StuderParser.VTType;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
@ -43,14 +51,6 @@ import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -21,12 +21,6 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus.sunspec-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus-sunspec" description="Modbus Binding SunSpec" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.sunspec/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -30,17 +30,17 @@ import org.openhab.binding.modbus.sunspec.internal.dto.ModelBlock;
|
||||
import org.openhab.binding.modbus.sunspec.internal.parser.CommonModelParser;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.exception.ModbusSlaveErrorResponseException;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.exception.ModbusSlaveErrorResponseException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -26,6 +26,12 @@ import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
|
||||
import org.openhab.binding.modbus.sunspec.internal.SunSpecConfiguration;
|
||||
import org.openhab.binding.modbus.sunspec.internal.dto.ModelBlock;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
@ -38,12 +44,6 @@ import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -22,10 +22,10 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.sunspec.internal.InverterStatus;
|
||||
import org.openhab.binding.modbus.sunspec.internal.dto.InverterModelBlock;
|
||||
import org.openhab.binding.modbus.sunspec.internal.parser.InverterModelParser;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -18,8 +18,8 @@ import static org.openhab.core.library.unit.Units.*;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.sunspec.internal.dto.MeterModelBlock;
|
||||
import org.openhab.binding.modbus.sunspec.internal.parser.MeterModelParser;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -15,10 +15,10 @@ package org.openhab.binding.modbus.sunspec.internal.parser;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Base class for parsers with some helper methods
|
||||
|
@ -17,8 +17,8 @@ import java.nio.charset.Charset;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.sunspec.internal.SunSpecConstants;
|
||||
import org.openhab.binding.modbus.sunspec.internal.dto.CommonModelBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -15,7 +15,7 @@ package org.openhab.binding.modbus.sunspec.internal.parser;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.sunspec.internal.SunSpecConstants;
|
||||
import org.openhab.binding.modbus.sunspec.internal.dto.InverterModelBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parses inverter modbus data into an InverterModelBlock
|
||||
|
@ -15,7 +15,7 @@ package org.openhab.binding.modbus.sunspec.internal.parser;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.modbus.sunspec.internal.SunSpecConstants;
|
||||
import org.openhab.binding.modbus.sunspec.internal.dto.MeterModelBlock;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* Parser for sunspec compatible meters
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.openhab.binding.modbus.sunspec.internal.parser;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
|
||||
/**
|
||||
* General interface for sunspec parsers
|
||||
|
@ -14,13 +14,4 @@
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Modbus Binding</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.modbus-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-modbus" description="Modbus Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-modbus</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -18,19 +18,19 @@ import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusFailureCallback;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadCallback;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteCallback;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
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.thing.binding.BridgeHandler;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusFailureCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
|
||||
/**
|
||||
* This is a convenience class to interact with the Thing's {@link ModbusCommunicationInterface}.
|
||||
|
@ -15,8 +15,8 @@ package org.openhab.binding.modbus.handler;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.Identifiable;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
|
||||
/**
|
||||
* Base interface for thing handlers of endpoint things
|
||||
|
@ -24,6 +24,15 @@ import org.openhab.binding.modbus.internal.AtomicStampedValue;
|
||||
import org.openhab.binding.modbus.internal.ModbusBindingConstantsInternal;
|
||||
import org.openhab.binding.modbus.internal.config.ModbusPollerConfiguration;
|
||||
import org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants;
|
||||
import org.openhab.core.io.transport.modbus.ModbusFailureCallback;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadCallback;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.PollTask;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -33,15 +42,6 @@ import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants;
|
||||
import org.openhab.io.transport.modbus.ModbusFailureCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -18,8 +18,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
|
||||
/**
|
||||
* The {@link ModbusBinding} class defines common constants, which are
|
||||
|
@ -23,13 +23,13 @@ import org.openhab.binding.modbus.handler.ModbusPollerThingHandler;
|
||||
import org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler;
|
||||
import org.openhab.binding.modbus.internal.handler.ModbusSerialThingHandler;
|
||||
import org.openhab.binding.modbus.internal.handler.ModbusTcpThingHandler;
|
||||
import org.openhab.core.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.openhab.io.transport.modbus.ModbusManager;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -17,16 +17,16 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler;
|
||||
import org.openhab.binding.modbus.internal.ModbusConfigurationException;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -31,6 +31,23 @@ import org.openhab.binding.modbus.internal.ModbusBindingConstantsInternal;
|
||||
import org.openhab.binding.modbus.internal.ModbusConfigurationException;
|
||||
import org.openhab.binding.modbus.internal.Transformation;
|
||||
import org.openhab.binding.modbus.internal.config.ModbusDataConfiguration;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.core.io.transport.modbus.AsyncModbusWriteResult;
|
||||
import org.openhab.core.io.transport.modbus.BitArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants;
|
||||
import org.openhab.core.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.core.io.transport.modbus.exception.ModbusConnectionException;
|
||||
import org.openhab.core.io.transport.modbus.exception.ModbusTransportException;
|
||||
import org.openhab.core.io.transport.modbus.json.WriteRequestJsonUtilities;
|
||||
import org.openhab.core.library.items.ContactItem;
|
||||
import org.openhab.core.library.items.DateTimeItem;
|
||||
import org.openhab.core.library.items.DimmerItem;
|
||||
@ -55,23 +72,6 @@ import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusFailure;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusWriteResult;
|
||||
import org.openhab.io.transport.modbus.BitArray;
|
||||
import org.openhab.io.transport.modbus.ModbusBitUtilities;
|
||||
import org.openhab.io.transport.modbus.ModbusCommunicationInterface;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteCoilRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.exception.ModbusConnectionException;
|
||||
import org.openhab.io.transport.modbus.exception.ModbusTransportException;
|
||||
import org.openhab.io.transport.modbus.json.WriteRequestJsonUtilities;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.FrameworkUtil;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -21,12 +21,12 @@ import org.openhab.binding.modbus.discovery.internal.ModbusEndpointDiscoveryServ
|
||||
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.internal.ModbusConfigurationException;
|
||||
import org.openhab.binding.modbus.internal.config.ModbusSerialConfiguration;
|
||||
import org.openhab.core.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.ModbusSerialSlaveEndpoint;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSerialSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Endpoint thing handler for serial slaves
|
||||
|
@ -21,12 +21,12 @@ import org.openhab.binding.modbus.discovery.internal.ModbusEndpointDiscoveryServ
|
||||
import org.openhab.binding.modbus.handler.EndpointNotInitializedException;
|
||||
import org.openhab.binding.modbus.internal.ModbusConfigurationException;
|
||||
import org.openhab.binding.modbus.internal.config.ModbusTcpConfiguration;
|
||||
import org.openhab.core.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.core.io.transport.modbus.endpoint.ModbusTCPSlaveEndpoint;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.io.transport.modbus.ModbusManager;
|
||||
import org.openhab.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusTCPSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Endpoint thing handler for TCP slaves
|
||||
|
@ -1,20 +0,0 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab-addons
|
||||
|
||||
== Third-party Content
|
||||
|
||||
jsoup
|
||||
* License: MIT License
|
||||
* Project: https://jsoup.org/
|
||||
* Source: https://github.com/jhy/jsoup
|
@ -1,3 +0,0 @@
|
||||
# Modbus Transport
|
||||
|
||||
This transport provides a nice abstraction for modbus.
|
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.io.transport.modbus</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: IO :: Modbus Transport</name>
|
||||
|
||||
<properties>
|
||||
<bnd.importpackage>gnu.io;version="[3.12,6)"</bnd.importpackage>
|
||||
<dep.noembedding>commons-pool2</dep.noembedding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.8.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.wimpi</groupId>
|
||||
<artifactId>jamod</artifactId>
|
||||
<version>1.2.4.OH</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.io.transport.modbus-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-transport-modbus" description="Modbus Transport" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-serial</feature>
|
||||
<bundle dependency="true">mvn:org.apache.commons/commons-pool2/2.8.1</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.io.transport.modbus/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -1,65 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Encapsulates result of modbus read operations
|
||||
*
|
||||
* @author Nagy Attila Gabor - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsyncModbusFailure<R> {
|
||||
private final R request;
|
||||
|
||||
private final Exception cause;
|
||||
|
||||
public AsyncModbusFailure(R request, Exception cause) {
|
||||
Objects.requireNonNull(request, "Request must not be null!");
|
||||
Objects.requireNonNull(cause, "Cause must not be null!");
|
||||
this.request = request;
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request matching this response
|
||||
*
|
||||
* @return request object
|
||||
*/
|
||||
public R getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cause of error
|
||||
*
|
||||
* @return exception representing error
|
||||
*/
|
||||
public Exception getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("AsyncModbusReadResult(");
|
||||
builder.append("request = ");
|
||||
builder.append(request);
|
||||
builder.append(", error = ");
|
||||
builder.append(cause);
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Encapsulates result of modbus read operations
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsyncModbusReadResult {
|
||||
|
||||
private final ModbusReadRequestBlueprint request;
|
||||
|
||||
private final Optional<BitArray> bits;
|
||||
|
||||
private final Optional<ModbusRegisterArray> registers;
|
||||
|
||||
public AsyncModbusReadResult(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) {
|
||||
Objects.requireNonNull(request, "Request must not be null!");
|
||||
Objects.requireNonNull(registers, "Registers must not be null!");
|
||||
this.request = request;
|
||||
this.registers = Optional.of(registers);
|
||||
this.bits = Optional.empty();
|
||||
}
|
||||
|
||||
public AsyncModbusReadResult(ModbusReadRequestBlueprint request, BitArray bits) {
|
||||
Objects.requireNonNull(request, "Request must not be null!");
|
||||
Objects.requireNonNull(bits, "Bits must not be null!");
|
||||
this.request = request;
|
||||
this.registers = Optional.empty();
|
||||
this.bits = Optional.of(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request matching this response
|
||||
*
|
||||
* @return request object
|
||||
*/
|
||||
public ModbusReadRequestBlueprint getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "coil" or "discrete input" bit data in the case of no errors
|
||||
*
|
||||
* @return bit data
|
||||
*/
|
||||
public Optional<BitArray> getBits() {
|
||||
return bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "input register" or "holding register" data in the case of no errors
|
||||
*
|
||||
* @return register data
|
||||
*/
|
||||
public Optional<ModbusRegisterArray> getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("AsyncModbusReadResult(");
|
||||
builder.append("request = ");
|
||||
builder.append(request);
|
||||
bits.ifPresent(bits -> {
|
||||
builder.append(", bits = ");
|
||||
builder.append(bits);
|
||||
});
|
||||
registers.ifPresent(registers -> {
|
||||
builder.append(", registers = ");
|
||||
builder.append(registers);
|
||||
});
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Encapsulates result of modbus write operations
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsyncModbusWriteResult {
|
||||
|
||||
private final ModbusWriteRequestBlueprint request;
|
||||
|
||||
private final ModbusResponse response;
|
||||
|
||||
public AsyncModbusWriteResult(ModbusWriteRequestBlueprint request, ModbusResponse response) {
|
||||
Objects.requireNonNull(request, "Request must not be null!");
|
||||
Objects.requireNonNull(response, "Response must not be null!");
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request matching this response
|
||||
*
|
||||
* @return request object
|
||||
*/
|
||||
public ModbusWriteRequestBlueprint getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response
|
||||
*
|
||||
* @return response
|
||||
*/
|
||||
public ModbusResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("AsyncModbusWriteResult(");
|
||||
builder.append("request = ");
|
||||
builder.append(request);
|
||||
builder.append(", response = ");
|
||||
builder.append(response);
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
141
bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BitArray.java
141
bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BitArray.java
@ -1,141 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Class that implements a collection for
|
||||
* bits
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BitArray implements Iterable<Boolean> {
|
||||
|
||||
private final BitSet wrapped;
|
||||
private final int length;
|
||||
|
||||
public BitArray(int nbits) {
|
||||
this(new BitSet(nbits), nbits);
|
||||
}
|
||||
|
||||
public BitArray(boolean... bits) {
|
||||
this(bitSetFromBooleans(bits), bits.length);
|
||||
}
|
||||
|
||||
public BitArray(BitSet wrapped, int length) {
|
||||
this.wrapped = wrapped;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
private static BitSet bitSetFromBooleans(boolean... bits) {
|
||||
BitSet bitSet = new BitSet(bits.length);
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
bitSet.set(i, bits[i]);
|
||||
}
|
||||
|
||||
return bitSet;
|
||||
}
|
||||
|
||||
private boolean sizeAndValuesEquals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof BitArray)) {
|
||||
return false;
|
||||
}
|
||||
BitArray other = (BitArray) obj;
|
||||
if (this.size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < this.size(); i++) {
|
||||
if (this.getBit(i) != other.getBit(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of the bit at the given index
|
||||
*
|
||||
* Index 0 matches LSB (rightmost) bit
|
||||
* <p>
|
||||
*
|
||||
* @param index the index of the bit to be returned.
|
||||
* @return true if the bit at the specified index is set,
|
||||
* false otherwise.
|
||||
* @throws IndexOutOfBoundsException if the index is out of bounds.
|
||||
*/
|
||||
public boolean getBit(int index) {
|
||||
if (index >= size()) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return this.wrapped.get(index);
|
||||
}
|
||||
|
||||
public void setBit(int index, boolean value) {
|
||||
if (value) {
|
||||
this.wrapped.set(index);
|
||||
} else {
|
||||
this.wrapped.clear(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of bits stored in this instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int size() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("BitArray(bits=").append(length == 0 ? "<empty>" : toBinaryString()).append(")")
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Boolean> iterator() {
|
||||
return IntStream.range(0, size()).mapToObj(i -> getBit(i)).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return sizeAndValuesEquals(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data as binary string
|
||||
*
|
||||
* For example, 0010
|
||||
*
|
||||
* @return string representing the data
|
||||
*/
|
||||
public String toBinaryString() {
|
||||
final StringBuilder buffer = new StringBuilder(size());
|
||||
IntStream.range(0, size()).mapToObj(i -> getBit(i) ? '1' : '0').forEach(buffer::append);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
@ -1,759 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.NotImplementedException;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.io.transport.modbus.ModbusConstants.ValueType;
|
||||
|
||||
/**
|
||||
* Utilities for working with binary data.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusBitUtilities {
|
||||
|
||||
/**
|
||||
* Read data from registers and convert the result to DecimalType
|
||||
* Interpretation of <tt>index</tt> goes as follows depending on type
|
||||
*
|
||||
* BIT:
|
||||
* - a single bit is read from the registers
|
||||
* - indices between 0...15 (inclusive) represent bits of the first register
|
||||
* - indices between 16...31 (inclusive) represent bits of the second register, etc.
|
||||
* - index 0 refers to the least significant bit of the first register
|
||||
* - index 1 refers to the second least significant bit of the first register, etc.
|
||||
* INT8:
|
||||
* - a byte (8 bits) from the registers is interpreted as signed integer
|
||||
* - index 0 refers to low byte of the first register, 1 high byte of first register
|
||||
* - index 2 refers to low byte of the second register, 3 high byte of second register, etc.
|
||||
* - it is assumed that each high and low byte is encoded in most significant bit first order
|
||||
* UINT8:
|
||||
* - same as INT8 except value is interpreted as unsigned integer
|
||||
* INT16:
|
||||
* - register with index (counting from zero) is interpreted as 16 bit signed integer.
|
||||
* - it is assumed that each register is encoded in most significant bit first order
|
||||
* UINT16:
|
||||
* - same as INT16 except value is interpreted as unsigned integer
|
||||
* INT32:
|
||||
* - registers (index) and (index + 1) are interpreted as signed 32bit integer.
|
||||
* - it assumed that the first register contains the most significant 16 bits
|
||||
* - it is assumed that each register is encoded in most significant bit first order
|
||||
* INT32_SWAP:
|
||||
* - Same as INT32 but registers swapped
|
||||
* UINT32:
|
||||
* - same as INT32 except value is interpreted as unsigned integer
|
||||
* UINT32_SWAP:
|
||||
* - same as INT32_SWAP except value is interpreted as unsigned integer
|
||||
* FLOAT32:
|
||||
* - registers (index) and (index + 1) are interpreted as signed 32bit floating point number.
|
||||
* - it assumed that the first register contains the most significant 16 bits
|
||||
* - it is assumed that each register is encoded in most significant bit first order
|
||||
* - floating point NaN and infinity will return as empty optional
|
||||
* FLOAT32_SWAP:
|
||||
* - Same as FLOAT32 but registers swapped
|
||||
* INT64:
|
||||
* - registers (index), (index + 1), (index + 2), (index + 3) are interpreted as signed 64bit integer.
|
||||
* - it assumed that the first register contains the most significant 16 bits
|
||||
* - it is assumed that each register is encoded in most significant bit first order
|
||||
* INT64_SWAP:
|
||||
* - same as INT64 but registers swapped, that is, registers (index + 3), (index + 2), (index + 1), (index + 1) are
|
||||
* interpreted as signed 64bit integer
|
||||
* UINT64:
|
||||
* - same as INT64 except value is interpreted as unsigned integer
|
||||
* UINT64_SWAP:
|
||||
* - same as INT64_SWAP except value is interpreted as unsigned integer
|
||||
*
|
||||
* @param registers list of registers, each register represent 16bit of data
|
||||
* @param index zero based item index. Interpretation of this depends on type, see examples above.
|
||||
* With type larger or equal to 16 bits, the index tells the register index to start reading
|
||||
* from.
|
||||
* With type less than 16 bits, the index tells the N'th item to read from the registers.
|
||||
* @param type item type, e.g. unsigned 16bit integer (<tt>ModbusBindingProvider.ValueType.UINT16</tt>)
|
||||
* @return number representation queried value, <tt>DecimalType</tt>. Empty optional is returned
|
||||
* with NaN and infinity floating point values
|
||||
* @throws NotImplementedException in cases where implementation is lacking for the type. This can be considered a
|
||||
* bug
|
||||
* @throws IllegalArgumentException when <tt>index</tt> is out of bounds of registers
|
||||
*
|
||||
*/
|
||||
public static Optional<DecimalType> extractStateFromRegisters(ModbusRegisterArray registers, int index,
|
||||
ModbusConstants.ValueType type) {
|
||||
byte[] bytes = registers.getBytes();
|
||||
switch (type) {
|
||||
case BIT:
|
||||
return Optional.of(new DecimalType(extractBit(bytes, index)));
|
||||
case INT8: {
|
||||
int registerIndex = index / 2;
|
||||
boolean hiByte = index % 2 == 1;
|
||||
return Optional.of(new DecimalType(extractSInt8(bytes, registerIndex, hiByte)));
|
||||
}
|
||||
case UINT8: {
|
||||
int registerIndex = index / 2;
|
||||
boolean hiByte = index % 2 == 1;
|
||||
return Optional.of(new DecimalType(extractUInt8(bytes, registerIndex, hiByte)));
|
||||
}
|
||||
case INT16:
|
||||
return Optional.of(new DecimalType(extractSInt16(bytes, index * 2)));
|
||||
case UINT16:
|
||||
return Optional.of(new DecimalType(extractUInt16(bytes, index * 2)));
|
||||
case INT32:
|
||||
return Optional.of(new DecimalType(extractSInt32(bytes, index * 2)));
|
||||
case UINT32:
|
||||
return Optional.of(new DecimalType(extractUInt32(bytes, index * 2)));
|
||||
case FLOAT32:
|
||||
try {
|
||||
return Optional.of(new DecimalType(extractFloat32(bytes, index * 2)));
|
||||
} catch (NumberFormatException e) {
|
||||
// floating point NaN or infinity encountered
|
||||
return Optional.empty();
|
||||
}
|
||||
case INT64:
|
||||
return Optional.of(new DecimalType(extractSInt64(bytes, index * 2)));
|
||||
case UINT64:
|
||||
return Optional.of(new DecimalType(new BigDecimal(extractUInt64(bytes, index * 2))));
|
||||
case INT32_SWAP:
|
||||
return Optional.of(new DecimalType(extractSInt32Swap(bytes, index * 2)));
|
||||
case UINT32_SWAP:
|
||||
return Optional.of(new DecimalType(extractUInt32Swap(bytes, index * 2)));
|
||||
case FLOAT32_SWAP:
|
||||
try {
|
||||
return Optional.of(new DecimalType(extractFloat32Swap(bytes, index * 2)));
|
||||
} catch (NumberFormatException e) {
|
||||
// floating point NaN or infinity encountered
|
||||
return Optional.empty();
|
||||
}
|
||||
case INT64_SWAP:
|
||||
return Optional.of(new DecimalType(extractSInt64Swap(bytes, index * 2)));
|
||||
case UINT64_SWAP:
|
||||
return Optional.of(new DecimalType(new BigDecimal(extractUInt64Swap(bytes, index * 2))));
|
||||
default:
|
||||
throw new IllegalArgumentException(type.getConfigValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertIndexAndType(byte[] bytes, int index, ValueType type) {
|
||||
int typeBits = type.getBits();
|
||||
// for 8-bit types and larger, index specifies the index of the byte. For bits, index specifies the index of the
|
||||
// bit (of the whole data)
|
||||
int indexPositionAsBitIndex = Math.min(type.getBits(), 8) * index;
|
||||
int endBitIndex = indexPositionAsBitIndex + typeBits - 1;
|
||||
int lastValidIndex = bytes.length * 8 - 1;
|
||||
if (endBitIndex > lastValidIndex || index < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Index=%d with type=%s is out-of-bounds given registers of size %d ", index, type,
|
||||
bytes.length / 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract single bit from registers represented by sequence of bytes
|
||||
*
|
||||
* - indices between 0...15 (inclusive) represent bits of the first register
|
||||
* - indices between 16...31 (inclusive) represent bits of the second register, etc.
|
||||
* - index 0 refers to the least significant bit of the first register
|
||||
* - index 1 refers to the second least significant bit of the first register, etc.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of bit
|
||||
* @return 0 when bit is set, 1 otherwise
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static int extractBit(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.BIT);
|
||||
int registerIndex = index / 16;
|
||||
int bitIndexWithinRegister = index % 16;
|
||||
return extractBit(bytes, registerIndex, bitIndexWithinRegister);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract single bit from registers represented by sequence of bytes
|
||||
*
|
||||
* bitIndexWithinRegister between 0...15 (inclusive) represent bits of the first register, where 0 refers to the
|
||||
* least significant bit of the register, index 1 refers to the second least significant bit of the register, etc.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param registerIndex index of register. First register has index of 0.
|
||||
* @param bitIndexWithinRegister bit index within the register
|
||||
* @return 0 when bit is set, 1 otherwise
|
||||
* @throws IllegalArgumentException when registerIndex and/or bitIndexWithinRegister is out of bounds
|
||||
*/
|
||||
public static int extractBit(byte[] bytes, int registerIndex, int bitIndexWithinRegister) {
|
||||
if (bitIndexWithinRegister < 0 || bitIndexWithinRegister > 15) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("bitIndexWithinRegister=%d is out-of-bounds (max 15)", bitIndexWithinRegister));
|
||||
} else if (registerIndex < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("registerIndex=%d is out-of-bounds", bitIndexWithinRegister));
|
||||
}
|
||||
boolean hiByte = bitIndexWithinRegister >= 8;
|
||||
int indexWithinByte = bitIndexWithinRegister % 8;
|
||||
int byteIndex = 2 * registerIndex + (hiByte ? 0 : 1);
|
||||
if (byteIndex >= bytes.length) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"registerIndex=%d, bitIndexWithinRegister=%d is out-of-bounds with registers of size %d",
|
||||
registerIndex, bitIndexWithinRegister, bytes.length / 2));
|
||||
}
|
||||
return ((bytes[byteIndex] >>> indexWithinByte) & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 8-bit integer (byte) from registers represented by sequence of bytes
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param registerIndex index of register. First register has index of 0.
|
||||
* @param hiByte whether to extract hi byte or lo byte
|
||||
* @return 0 when bit is set, 1 otherwise
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static byte extractSInt8(byte[] bytes, int registerIndex, boolean hiByte) {
|
||||
int byteIndex = 2 * registerIndex + (hiByte ? 0 : 1);
|
||||
byte signed = extractSInt8(bytes, byteIndex);
|
||||
return signed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 8-bit integer (byte) from registers represented by sequence of bytes
|
||||
*
|
||||
* - index 0 refers to low byte of the first register, 1 high byte of first register
|
||||
* - index 2 refers to low byte of the second register, 3 high byte of second register, etc.
|
||||
* - it is assumed that each high and low byte is encoded in most significant bit first order
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param registerIndex index of register. First register has index of 0.
|
||||
* @param index index of the byte in registers
|
||||
* @return 0 when bit is set, 1 otherwise
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static byte extractSInt8(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.INT8);
|
||||
byte signed = bytes[index];
|
||||
return signed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 8-bit integer (byte) from registers represented by sequence of bytes
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param registerIndex index of register. First register has index of 0.
|
||||
* @param hiByte whether to extract hi byte or lo byte
|
||||
* @return 0 when bit is set, 1 otherwise
|
||||
* @throws IllegalArgumentException when registerIndex is out of bounds
|
||||
*/
|
||||
public static short extractUInt8(byte[] bytes, int registerIndex, boolean hiByte) {
|
||||
int byteIndex = 2 * registerIndex + (hiByte ? 0 : 1);
|
||||
short unsigned = extractUInt8(bytes, byteIndex);
|
||||
return unsigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 8-bit integer (byte) from registers represented by sequence of bytes
|
||||
*
|
||||
* - index 0 refers to low byte of the first register, 1 high byte of first register
|
||||
* - index 2 refers to low byte of the second register, 3 high byte of second register, etc.
|
||||
* - it is assumed that each high and low byte is encoded in most significant bit first order
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param registerIndex index of register. First register has index of 0.
|
||||
* @param index index of the byte in registers
|
||||
* @return 0 when bit is set, 1 otherwise
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static short extractUInt8(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.UINT8);
|
||||
int signed = extractSInt8(bytes, index);
|
||||
short unsigned = (short) (signed & 0xff);
|
||||
assert unsigned >= 0;
|
||||
return unsigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 16-bit integer (short) from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of register. First register has index of 0.
|
||||
* @return register with index interpreted as 16 bit signed integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static short extractSInt16(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.INT16);
|
||||
int hi = (bytes[index] & 0xff);
|
||||
int lo = (bytes[index + 1] & 0xff);
|
||||
short signed = (short) ((hi << 8) | lo);
|
||||
return signed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 16-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of register. First register has index of 0.
|
||||
* @return register with index interpreted as 16 bit unsigned integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static int extractUInt16(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.UINT16);
|
||||
int signed = extractSInt16(bytes, index);
|
||||
int unsigned = signed & 0xffff;
|
||||
assert unsigned >= 0;
|
||||
return unsigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 32-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index) and (index+1) interpreted as 32 bit signed integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static int extractSInt32(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.INT32);
|
||||
int hi1 = bytes[index + 0] & 0xff;
|
||||
int lo1 = bytes[index + 1] & 0xff;
|
||||
int hi2 = bytes[index + 2] & 0xff;
|
||||
int lo2 = bytes[index + 3] & 0xff;
|
||||
int signed = (hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2;
|
||||
return signed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 32-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index) and (index+1) interpreted as 32 bit unsigned integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static long extractUInt32(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.UINT32);
|
||||
long signed = extractSInt32(bytes, index);
|
||||
long unsigned = signed & 0xffff_ffffL;
|
||||
assert unsigned >= 0;
|
||||
return unsigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 32-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* This is identical with extractSInt32, but with registers swapped.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index+1), (index) interpreted as 32 bit signed integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static int extractSInt32Swap(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.INT32_SWAP);
|
||||
// swapped order of registers, high 16 bits *follow* low 16 bits
|
||||
int hi1 = bytes[index + 2] & 0xff;
|
||||
int lo1 = bytes[index + 3] & 0xff;
|
||||
int hi2 = bytes[index + 0] & 0xff;
|
||||
int lo2 = bytes[index + 1] & 0xff;
|
||||
int signed = (hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2;
|
||||
return signed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 32-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* This is identical with extractUInt32, but with registers swapped.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index+1), (index) interpreted as 32 bit unsigned integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static long extractUInt32Swap(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.UINT32_SWAP);
|
||||
long signed = extractSInt32Swap(bytes, index);
|
||||
long unsigned = signed & 0xffff_ffffL;
|
||||
assert unsigned >= 0;
|
||||
return unsigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 64-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index), (index+1), (index+2), (index+3) interpreted as 64 bit signed integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static long extractSInt64(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.INT64);
|
||||
byte hi1 = (byte) (bytes[index + 0] & 0xff);
|
||||
byte lo1 = (byte) (bytes[index + 1] & 0xff);
|
||||
byte hi2 = (byte) (bytes[index + 2] & 0xff);
|
||||
byte lo2 = (byte) (bytes[index + 3] & 0xff);
|
||||
byte hi3 = (byte) (bytes[index + 4] & 0xff);
|
||||
byte lo3 = (byte) (bytes[index + 5] & 0xff);
|
||||
byte hi4 = (byte) (bytes[index + 6] & 0xff);
|
||||
byte lo4 = (byte) (bytes[index + 7] & 0xff);
|
||||
return new BigInteger(new byte[] { hi1, lo1, hi2, lo2, hi3, lo3, hi4, lo4 }).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 64-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index), (index+1), (index+2), (index+3) interpreted as 64 bit unsigned integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static BigInteger extractUInt64(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.UINT64);
|
||||
byte hi1 = (byte) (bytes[index + 0] & 0xff);
|
||||
byte lo1 = (byte) (bytes[index + 1] & 0xff);
|
||||
byte hi2 = (byte) (bytes[index + 2] & 0xff);
|
||||
byte lo2 = (byte) (bytes[index + 3] & 0xff);
|
||||
byte hi3 = (byte) (bytes[index + 4] & 0xff);
|
||||
byte lo3 = (byte) (bytes[index + 5] & 0xff);
|
||||
byte hi4 = (byte) (bytes[index + 6] & 0xff);
|
||||
byte lo4 = (byte) (bytes[index + 7] & 0xff);
|
||||
return new BigInteger(1, new byte[] { hi1, lo1, hi2, lo2, hi3, lo3, hi4, lo4 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 64-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* This is identical with extractInt64, but with registers swapped (registers with higher index before lower index).
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index+3), (index+2), (index+1), (index) interpreted as 64 bit signed integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static long extractSInt64Swap(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.INT64_SWAP);
|
||||
// Swapped order of registers
|
||||
byte hi1 = (byte) (bytes[index + 6] & 0xff);
|
||||
byte lo1 = (byte) (bytes[index + 7] & 0xff);
|
||||
byte hi2 = (byte) (bytes[index + 4] & 0xff);
|
||||
byte lo2 = (byte) (bytes[index + 5] & 0xff);
|
||||
byte hi3 = (byte) (bytes[index + 2] & 0xff);
|
||||
byte lo3 = (byte) (bytes[index + 3] & 0xff);
|
||||
byte hi4 = (byte) (bytes[index + 0] & 0xff);
|
||||
byte lo4 = (byte) (bytes[index + 1] & 0xff);
|
||||
return new BigInteger(new byte[] { hi1, lo1, hi2, lo2, hi3, lo3, hi4, lo4 }).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 64-bit integer from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* This is identical with extractUInt64, but with registers swapped (registers with higher index before lower
|
||||
* index).
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index+3), (index+2), (index+1), (index) interpreted as 64 bit unsigned integer
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static BigInteger extractUInt64Swap(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.UINT64_SWAP);
|
||||
// Swapped order of registers
|
||||
byte hi1 = (byte) (bytes[index + 6] & 0xff);
|
||||
byte lo1 = (byte) (bytes[index + 7] & 0xff);
|
||||
byte hi2 = (byte) (bytes[index + 4] & 0xff);
|
||||
byte lo2 = (byte) (bytes[index + 5] & 0xff);
|
||||
byte hi3 = (byte) (bytes[index + 2] & 0xff);
|
||||
byte lo3 = (byte) (bytes[index + 3] & 0xff);
|
||||
byte hi4 = (byte) (bytes[index + 0] & 0xff);
|
||||
byte lo4 = (byte) (bytes[index + 1] & 0xff);
|
||||
return new BigInteger(1, new byte[] { hi1, lo1, hi2, lo2, hi3, lo3, hi4, lo4 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract single-precision 32-bit IEEE 754 floating point from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* Note that this method can return floating point NaN and floating point infinity.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index), (index+1), (index+2), (index+3) interpreted as single-precision 32-bit IEEE 754
|
||||
* floating point
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static float extractFloat32(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.FLOAT32);
|
||||
int hi1 = bytes[index + 0] & 0xff;
|
||||
int lo1 = bytes[index + 1] & 0xff;
|
||||
int hi2 = bytes[index + 2] & 0xff;
|
||||
int lo2 = bytes[index + 3] & 0xff;
|
||||
int bits32 = (hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2;
|
||||
return Float.intBitsToFloat(bits32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract single-precision 32-bit IEEE 754 floating point from registers represented by sequence of bytes
|
||||
*
|
||||
* It is assumed that each register is encoded in most significant bit first order.
|
||||
*
|
||||
* This is identical with extractFloat32, but with registers swapped (registers with higher index before lower
|
||||
* index).
|
||||
*
|
||||
* Note that this method can return floating point NaN and floating point infinity.
|
||||
*
|
||||
* @param bytes registers represented by sequence of bytes
|
||||
* @param index index of first register. First register has index of 0.
|
||||
* @return registers (index+3), (index+2), (index+1), (index) interpreted as single-precision 32-bit IEEE 754
|
||||
* floating point
|
||||
* @throws IllegalArgumentException when index is out of bounds
|
||||
*/
|
||||
public static float extractFloat32Swap(byte[] bytes, int index) {
|
||||
assertIndexAndType(bytes, index, ValueType.FLOAT32_SWAP);
|
||||
// swapped order of registers, high 16 bits *follow* low 16 bits
|
||||
int hi1 = bytes[index + 2] & 0xff;
|
||||
int lo1 = bytes[index + 3] & 0xff;
|
||||
int hi2 = bytes[index + 0] & 0xff;
|
||||
int lo2 = bytes[index + 1] & 0xff;
|
||||
int bits32 = (hi1 << 24) | (lo1 << 16) | (hi2 << 8) | lo2;
|
||||
return Float.intBitsToFloat(bits32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from registers and convert the result to String
|
||||
* Strings should start the the first byte of a register, but could
|
||||
* have an odd number of characters.
|
||||
* Raw byte array values are converted using the charset parameter
|
||||
* and a maximum of length bytes are read. However reading stops at the first
|
||||
* NUL byte encountered.
|
||||
*
|
||||
* Registers are read in big-endian order, i.e. two registers consisting 4 bytes (ab, cd) are parsed as sequence of
|
||||
* bytes (a,b,c,d).
|
||||
*
|
||||
* @param registers list of registers, each register represent 16bit of data
|
||||
* @param registerIndex zero based register index. Registers are handled as 16bit registers,
|
||||
* this parameter defines the starting register.
|
||||
* @param length maximum length of string in 8bit characters (number of bytes considered)
|
||||
* @param charset the character set used to construct the string.
|
||||
* @return string representation queried value
|
||||
* @throws IllegalArgumentException when <tt>index</tt> is out of bounds of registers
|
||||
*/
|
||||
public static String extractStringFromRegisters(ModbusRegisterArray registers, int registerIndex, int length,
|
||||
Charset charset) {
|
||||
return extractStringFromBytes(registers.getBytes(), registerIndex * 2, length, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from bytes and convert the result to String
|
||||
*
|
||||
* Raw byte array values are converted using the charset parameter
|
||||
* and a maximum of length bytes are read. However reading stops at the first
|
||||
* NUL byte encountered.
|
||||
*
|
||||
* @param bytes bytes representing the registers
|
||||
* @param byteIndex zero based byte index
|
||||
* @param length maximum length of string in 8bit characters (number of bytes considered)
|
||||
* @param charset the character set used to construct the string.
|
||||
* @return string representation queried value
|
||||
* @throws IllegalArgumentException when <tt>index</tt> is out of bounds of registers
|
||||
*/
|
||||
public static String extractStringFromBytes(byte[] bytes, int byteIndex, int length, Charset charset) {
|
||||
if (byteIndex + length > bytes.length) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("byteIndex=%d with length=%d is out-of-bounds given registers of size %d", byteIndex,
|
||||
length, bytes.length));
|
||||
}
|
||||
if (byteIndex < 0) {
|
||||
throw new IllegalArgumentException("Negative index values are not supported");
|
||||
}
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException("Negative string length is not supported");
|
||||
}
|
||||
|
||||
int effectiveLength = length;
|
||||
|
||||
// Find first zero byte in registers and call reduce length such that we stop before it
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (bytes[byteIndex + i] == '\0') {
|
||||
effectiveLength = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new String(bytes, byteIndex, effectiveLength, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert command to array of registers using a specific value type
|
||||
*
|
||||
* @param command command to be converted
|
||||
* @param type value type to use in conversion
|
||||
* @return array of registers
|
||||
* @throws NotImplementedException in cases where implementation is lacking for the type. This is thrown with 1-bit
|
||||
* and 8-bit value types
|
||||
*/
|
||||
public static ModbusRegisterArray commandToRegisters(Command command, ModbusConstants.ValueType type) {
|
||||
DecimalType numericCommand;
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType) {
|
||||
numericCommand = translateCommand2Boolean(command).get() ? new DecimalType(BigDecimal.ONE)
|
||||
: DecimalType.ZERO;
|
||||
} else if (command instanceof DecimalType) {
|
||||
numericCommand = (DecimalType) command;
|
||||
} else {
|
||||
throw new NotImplementedException(String.format(
|
||||
"Command '%s' of class '%s' cannot be converted to registers. Please use OnOffType, OpenClosedType, or DecimalType commands.",
|
||||
command, command.getClass().getName()));
|
||||
}
|
||||
if (type.getBits() != 16 && type.getBits() != 32 && type.getBits() != 64) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Illegal type=%s (bits=%d). Only 16bit and 32bit types are supported", type, type.getBits()));
|
||||
}
|
||||
switch (type) {
|
||||
case INT16:
|
||||
case UINT16: {
|
||||
short shortValue = numericCommand.shortValue();
|
||||
// big endian byte ordering
|
||||
byte hi = (byte) (shortValue >> 8);
|
||||
byte lo = (byte) shortValue;
|
||||
return new ModbusRegisterArray(new byte[] { hi, lo });
|
||||
}
|
||||
case INT32:
|
||||
case UINT32: {
|
||||
int intValue = numericCommand.intValue();
|
||||
// big endian byte ordering
|
||||
byte hi1 = (byte) (intValue >> 24);
|
||||
byte lo1 = (byte) (intValue >> 16);
|
||||
byte hi2 = (byte) (intValue >> 8);
|
||||
byte lo2 = (byte) intValue;
|
||||
return new ModbusRegisterArray(new byte[] { hi1, lo1, hi2, lo2 });
|
||||
}
|
||||
case INT32_SWAP:
|
||||
case UINT32_SWAP: {
|
||||
int intValue = numericCommand.intValue();
|
||||
// big endian byte ordering
|
||||
byte hi1 = (byte) (intValue >> 24);
|
||||
byte lo1 = (byte) (intValue >> 16);
|
||||
byte hi2 = (byte) (intValue >> 8);
|
||||
byte lo2 = (byte) intValue;
|
||||
// Swapped order of registers
|
||||
return new ModbusRegisterArray(new byte[] { hi2, lo2, hi1, lo1 });
|
||||
}
|
||||
case FLOAT32: {
|
||||
float floatValue = numericCommand.floatValue();
|
||||
int intBits = Float.floatToIntBits(floatValue);
|
||||
// big endian byte ordering
|
||||
byte hi1 = (byte) (intBits >> 24);
|
||||
byte lo1 = (byte) (intBits >> 16);
|
||||
byte hi2 = (byte) (intBits >> 8);
|
||||
byte lo2 = (byte) intBits;
|
||||
return new ModbusRegisterArray(new byte[] { hi1, lo1, hi2, lo2 });
|
||||
}
|
||||
case FLOAT32_SWAP: {
|
||||
float floatValue = numericCommand.floatValue();
|
||||
int intBits = Float.floatToIntBits(floatValue);
|
||||
// big endian byte ordering
|
||||
byte hi1 = (byte) (intBits >> 24);
|
||||
byte lo1 = (byte) (intBits >> 16);
|
||||
byte hi2 = (byte) (intBits >> 8);
|
||||
byte lo2 = (byte) intBits;
|
||||
// Swapped order of registers
|
||||
return new ModbusRegisterArray(new byte[] { hi2, lo2, hi1, lo1 });
|
||||
}
|
||||
case INT64:
|
||||
case UINT64: {
|
||||
long longValue = numericCommand.longValue();
|
||||
// big endian byte ordering
|
||||
byte hi1 = (byte) (longValue >> 56);
|
||||
byte lo1 = (byte) (longValue >> 48);
|
||||
byte hi2 = (byte) (longValue >> 40);
|
||||
byte lo2 = (byte) (longValue >> 32);
|
||||
byte hi3 = (byte) (longValue >> 24);
|
||||
byte lo3 = (byte) (longValue >> 16);
|
||||
byte hi4 = (byte) (longValue >> 8);
|
||||
byte lo4 = (byte) longValue;
|
||||
return new ModbusRegisterArray(new byte[] { hi1, lo1, hi2, lo2, hi3, lo3, hi4, lo4 });
|
||||
}
|
||||
case INT64_SWAP:
|
||||
case UINT64_SWAP: {
|
||||
long longValue = numericCommand.longValue();
|
||||
// big endian byte ordering
|
||||
byte hi1 = (byte) (longValue >> 56);
|
||||
byte lo1 = (byte) (longValue >> 48);
|
||||
byte hi2 = (byte) (longValue >> 40);
|
||||
byte lo2 = (byte) (longValue >> 32);
|
||||
byte hi3 = (byte) (longValue >> 24);
|
||||
byte lo3 = (byte) (longValue >> 16);
|
||||
byte hi4 = (byte) (longValue >> 8);
|
||||
byte lo4 = (byte) longValue;
|
||||
// Swapped order of registers
|
||||
return new ModbusRegisterArray(new byte[] { hi4, lo4, hi3, lo3, hi2, lo2, hi1, lo1 });
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException(
|
||||
String.format("Illegal type=%s. Missing implementation for this type", type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts command to a boolean
|
||||
*
|
||||
* true value is represented by {@link OnOffType.ON}, {@link OpenClosedType.OPEN}.
|
||||
* false value is represented by {@link OnOffType.OFF}, {@link OpenClosedType.CLOSED}.
|
||||
* Furthermore, {@link DecimalType} are converted to boolean true if they are unequal to zero.
|
||||
*
|
||||
* @param command to convert to boolean
|
||||
* @return Boolean value matching the command. Empty if command cannot be converted
|
||||
*/
|
||||
public static Optional<Boolean> translateCommand2Boolean(Command command) {
|
||||
if (command.equals(OnOffType.ON)) {
|
||||
return Optional.of(Boolean.TRUE);
|
||||
}
|
||||
if (command.equals(OnOffType.OFF)) {
|
||||
return Optional.of(Boolean.FALSE);
|
||||
}
|
||||
if (command.equals(OpenClosedType.OPEN)) {
|
||||
return Optional.of(Boolean.TRUE);
|
||||
}
|
||||
if (command.equals(OpenClosedType.CLOSED)) {
|
||||
return Optional.of(Boolean.FALSE);
|
||||
}
|
||||
if (command instanceof DecimalType) {
|
||||
return Optional.of(!command.equals(DecimalType.ZERO));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Interface for interacting with a particular modbus slave.
|
||||
*
|
||||
* When no further communication is expected with the slave, close the interface so that any underlying resources can be
|
||||
* freed.
|
||||
*
|
||||
* Close unregisters all the regular polls registered with registerRegularPoll. When endpoint's last
|
||||
* communication interface is closed, the connection is closed as well, no matter the what EndpointPoolConfiguration
|
||||
* says.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusCommunicationInterface extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* Get endpoint associated with this communication interface
|
||||
*
|
||||
* @return modbus slave endpoint
|
||||
*/
|
||||
public ModbusSlaveEndpoint getEndpoint();
|
||||
|
||||
/**
|
||||
* Submit one-time poll task. The method returns immediately, and the execution of the poll task will happen in
|
||||
* background.
|
||||
*
|
||||
* @param request request to send
|
||||
* @param callback callback to call with data
|
||||
* @param callback callback to call in case of failure
|
||||
* @return future representing the polled task
|
||||
* @throws IllegalStateException when this communication has been closed already
|
||||
*/
|
||||
public Future<?> submitOneTimePoll(ModbusReadRequestBlueprint request, ModbusReadCallback resultCallback,
|
||||
ModbusFailureCallback<ModbusReadRequestBlueprint> failureCallback);
|
||||
|
||||
/**
|
||||
* Register regularly polled task. The method returns immediately, and the execution of the poll task will happen in
|
||||
* the background.
|
||||
*
|
||||
* One can register only one regular poll task for triplet of (endpoint, request, callback).
|
||||
*
|
||||
* @param request request to send
|
||||
* @param pollPeriodMillis poll interval, in milliseconds
|
||||
* @param initialDelayMillis initial delay before starting polling, in milliseconds
|
||||
* @param callback callback to call with data
|
||||
* @param callback callback to call in case of failure
|
||||
* @return poll task representing the regular poll
|
||||
* @throws IllegalStateException when this communication has been closed already
|
||||
*/
|
||||
public PollTask registerRegularPoll(ModbusReadRequestBlueprint request, long pollPeriodMillis,
|
||||
long initialDelayMillis, ModbusReadCallback resultCallback,
|
||||
ModbusFailureCallback<ModbusReadRequestBlueprint> failureCallback);
|
||||
|
||||
/**
|
||||
* Unregister regularly polled task
|
||||
*
|
||||
* If this communication interface is closed already, the method returns immediately with false return value
|
||||
*
|
||||
* @param task poll task to unregister
|
||||
* @return whether poll task was unregistered. Poll task is not unregistered in case of unexpected errors or
|
||||
* in the case where the poll task is not registered in the first place
|
||||
*/
|
||||
public boolean unregisterRegularPoll(PollTask task);
|
||||
|
||||
/**
|
||||
* Submit one-time write task. The method returns immediately, and the execution of the task will happen in
|
||||
* background.
|
||||
*
|
||||
* @param request request to send
|
||||
* @param callback callback to call with response
|
||||
* @param callback callback to call in case of failure
|
||||
* @return future representing the task
|
||||
* @throws IllegalStateException when this communication has been closed already
|
||||
*/
|
||||
public Future<?> submitOneTimeWrite(ModbusWriteRequestBlueprint request, ModbusWriteCallback resultCallback,
|
||||
ModbusFailureCallback<ModbusWriteRequestBlueprint> failureCallback);
|
||||
|
||||
/**
|
||||
* Close this communication interface and try to free all resources associated with it
|
||||
*
|
||||
* Upon close, all polling tasks registered by this instance are unregistered. In addition, connections are closed
|
||||
* eagerly if this was the last connection interface pointing to the endpoint.
|
||||
*
|
||||
* After close, the communication interface cannot be used to communicate with the device.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void close() throws Exception;
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Constants for Modbus transport
|
||||
*
|
||||
* == Regarding maximum read and write limits ==
|
||||
*
|
||||
* Maximum number of registers that are allowed to be read.
|
||||
*
|
||||
* The Modbus protocol has many intepretation on maximum data size of messages. Good reference is here:
|
||||
* https://wingpath.co.uk/manpage.php?product=modtest&page=message_limits.html
|
||||
*
|
||||
* We try to follow modern specification here (V1.1B3):
|
||||
* https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf. See section 4.1 Protocol Specification in the
|
||||
* specification.
|
||||
*
|
||||
* According to V1.1B3, maximum size for PDU is 253 bytes, making maximum ADU size 256 (RTU) or 260 (TCP).
|
||||
*
|
||||
* In the spec section 6, one can see maximum values for read and write counts.
|
||||
*
|
||||
* Note that this is not the only interpretation -- some sources limit the ADU to 256 also with TCP.
|
||||
* In some cases, slaves cannot take in so much data.
|
||||
*
|
||||
*
|
||||
* Reads are limited by response PDU size.
|
||||
* Writes (FC15 & FC16) are limited by write request ADU size.
|
||||
*
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusConstants {
|
||||
|
||||
/**
|
||||
* Value types for different number types.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
public static enum ValueType {
|
||||
BIT("bit", 1),
|
||||
INT8("int8", 8),
|
||||
UINT8("uint8", 8),
|
||||
INT16("int16", 16),
|
||||
UINT16("uint16", 16),
|
||||
INT32("int32", 32),
|
||||
UINT32("uint32", 32),
|
||||
FLOAT32("float32", 32),
|
||||
INT64("int64", 64),
|
||||
UINT64("uint64", 64),
|
||||
|
||||
INT32_SWAP("int32_swap", 32),
|
||||
UINT32_SWAP("uint32_swap", 32),
|
||||
FLOAT32_SWAP("float32_swap", 32),
|
||||
INT64_SWAP("int64_swap", 64),
|
||||
UINT64_SWAP("uint64_swap", 64);
|
||||
|
||||
private final String configValue;
|
||||
private final int bits;
|
||||
|
||||
ValueType(String configValue, int bits) {
|
||||
this.configValue = configValue;
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of bits represented by this ValueType
|
||||
*
|
||||
* @return number of bits
|
||||
*/
|
||||
public int getBits() {
|
||||
return bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns config value to refer to this value type
|
||||
*
|
||||
* @return config value as string
|
||||
*/
|
||||
public String getConfigValue() {
|
||||
return configValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns config value
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getConfigValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs ValueType given the config value string.
|
||||
*
|
||||
* @param configValueType config value that will be parsed to ValueType
|
||||
* @return ValueType matching the config value
|
||||
* @throws IllegalArgumentException with unknown value types
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
public static @NonNull ValueType fromConfigValue(@Nullable String configValueType)
|
||||
throws IllegalArgumentException {
|
||||
return Stream.of(ValueType.values()).filter(v -> v.getConfigValue().equals(configValueType)).findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid valueType " + configValueType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of coils or discrete inputs that are allowed to be read.
|
||||
* Limitation by Modbus protocol V1.1B3, 6.1 definition of Read Holding registers.
|
||||
*/
|
||||
public static final int MAX_BITS_READ_COUNT = 2000;
|
||||
/**
|
||||
* Maximum number of registers that are allowed to be read.
|
||||
* Limitation by Modbus protocol V1.1B3, 6.3 definition of Read Coils.
|
||||
*/
|
||||
public static final int MAX_REGISTERS_READ_COUNT = 125;
|
||||
/**
|
||||
* Maximum number of coils or discrete inputs that are allowed to be written.
|
||||
* Limitation by Modbus protocol V1.1B3, 6.11 definition of Write Multiple coils.
|
||||
*/
|
||||
public static final int MAX_BITS_WRITE_COUNT = 1968;
|
||||
/**
|
||||
* Maximum number of registers that are allowed to be written.
|
||||
* Limitation by Modbus protocol V1.1B3, 6.12 definition of Write Multiple registers.
|
||||
*/
|
||||
public static final int MAX_REGISTERS_WRITE_COUNT = 123;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Callback used to report failure in Modbus
|
||||
*
|
||||
* @author Nagy Attila Gabor - Initial contribution
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@NonNullByDefault
|
||||
public interface ModbusFailureCallback<R> {
|
||||
/**
|
||||
* Callback handling response with error
|
||||
*
|
||||
* @param asyncModbusFailure details of the failure
|
||||
*/
|
||||
void handle(AsyncModbusFailure<R> failure);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.io.transport.modbus.endpoint.EndpointPoolConfiguration;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* ModbusManager is the main interface for interacting with Modbus slaves
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusManager {
|
||||
|
||||
/**
|
||||
* Open communication interface to endpoint
|
||||
*
|
||||
* @param endpoint endpoint pointing to modbus slave
|
||||
* @param configuration configuration for the endpoint
|
||||
* @return Communication interface for interacting with the slave
|
||||
* @throws IllegalArgumentException if there is already open communication interface with same endpoint but
|
||||
* differing configuration
|
||||
*/
|
||||
public ModbusCommunicationInterface newModbusCommunicationInterface(ModbusSlaveEndpoint endpoint,
|
||||
@Nullable EndpointPoolConfiguration configuration) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get general configuration settings applied to a given endpoint
|
||||
*
|
||||
* Note that default configuration settings are returned in case the endpoint has not been configured.
|
||||
*
|
||||
* @param endpoint endpoint to query
|
||||
* @return general connection settings of the given endpoint
|
||||
*/
|
||||
public @Nullable EndpointPoolConfiguration getEndpointPoolConfiguration(ModbusSlaveEndpoint endpoint);
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Interface for read callbacks
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@NonNullByDefault
|
||||
public interface ModbusReadCallback extends ModbusResultCallback {
|
||||
|
||||
/**
|
||||
* Callback handling response data
|
||||
*
|
||||
* @param result result of the read operation
|
||||
*/
|
||||
void handle(AsyncModbusReadResult result);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
/**
|
||||
* Modbus read function codes supported by this transport
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
public enum ModbusReadFunctionCode {
|
||||
READ_COILS,
|
||||
READ_INPUT_DISCRETES,
|
||||
READ_MULTIPLE_REGISTERS,
|
||||
READ_INPUT_REGISTERS
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import net.wimpi.modbus.Modbus;
|
||||
|
||||
/**
|
||||
* Implementation of immutable representation of modbus read request
|
||||
*
|
||||
* Equals and hashCode implemented keeping {@link PollTask} in mind: two instances of this class are considered the same
|
||||
* if they have
|
||||
* the equal parameters (same slave id, start, length, function code and maxTries).
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusReadRequestBlueprint {
|
||||
private static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
private final int slaveId;
|
||||
private final ModbusReadFunctionCode functionCode;
|
||||
private final int start;
|
||||
private final int length;
|
||||
private final int maxTries;
|
||||
|
||||
public ModbusReadRequestBlueprint(int slaveId, ModbusReadFunctionCode functionCode, int start, int length,
|
||||
int maxTries) {
|
||||
this.slaveId = slaveId;
|
||||
this.functionCode = functionCode;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
this.maxTries = maxTries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unit identifier of this
|
||||
* <tt>ModbusMessage</tt> as <tt>int</tt>.<br>
|
||||
* The identifier is a 1-byte non negative
|
||||
* integer value valid in the range of 0-255.
|
||||
* <p>
|
||||
*
|
||||
* @return the unit identifier as <tt>int</tt>.
|
||||
*/
|
||||
public int getUnitID() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
public int getReference() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public ModbusReadFunctionCode getFunctionCode() {
|
||||
return functionCode;
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of tries to execute the request, when request fails
|
||||
*
|
||||
* For example, number 1 means on try only with no re-tries.
|
||||
*
|
||||
* @return number of maximum tries
|
||||
*/
|
||||
public int getMaxTries() {
|
||||
return maxTries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol identifier of this
|
||||
* <tt>ModbusMessage</tt> as <tt>int</tt>.<br>
|
||||
* The identifier is a 2-byte (short) non negative
|
||||
* integer value valid in the range of 0-65535.
|
||||
* <p>
|
||||
*
|
||||
* @return the protocol identifier as <tt>int</tt>.
|
||||
*/
|
||||
public int getProtocolID() {
|
||||
return Modbus.DEFAULT_PROTOCOL_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(81, 3).append(slaveId).append(functionCode).append(start).append(length)
|
||||
.append(maxTries).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle).append("slaveId", slaveId).append("functionCode", functionCode)
|
||||
.append("start", start).append("length", length).append("maxTries", maxTries).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
ModbusReadRequestBlueprint rhs = (ModbusReadRequestBlueprint) obj;
|
||||
return new EqualsBuilder().append(slaveId, rhs.slaveId).append(functionCode, rhs.functionCode)
|
||||
.append(start, rhs.start).append(length, rhs.length).isEquals();
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
|
||||
/**
|
||||
* Immutable {@link ModbusRegisterArray} implementation
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusRegisterArray {
|
||||
|
||||
private final byte[] bytes;
|
||||
|
||||
public ModbusRegisterArray(byte... bytes) {
|
||||
if (bytes.length % 2 != 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.bytes = Arrays.copyOf(bytes, bytes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct plain <code>ModbusRegisterArray</code> array from register values
|
||||
*
|
||||
* @param registerValues register values, each <code>int</code> corresponding to one register
|
||||
* @return
|
||||
*/
|
||||
public ModbusRegisterArray(int... registerValues) {
|
||||
bytes = new byte[registerValues.length * 2];
|
||||
for (int registerIndex = 0; registerIndex < registerValues.length; registerIndex++) {
|
||||
int register = registerValues[registerIndex] & 0xffff;
|
||||
// hi-byte
|
||||
bytes[registerIndex * 2] = (byte) (register >> 8);
|
||||
// lo byte
|
||||
bytes[registerIndex * 2 + 1] = (byte) register;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get register index i as unsigned integer
|
||||
*
|
||||
* @param i register index
|
||||
* @return register value interpreted as unsigned integer (big-endian byte ordering)
|
||||
*/
|
||||
public int getRegister(int i) {
|
||||
int hi = bytes[i * 2] & 0xff;
|
||||
int lo = bytes[i * 2 + 1] & 0xff;
|
||||
return ((hi << 8) | lo) & 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bytes representing the registers
|
||||
*
|
||||
*
|
||||
* Index 0: hi-byte of 1st register
|
||||
* Index 1: low-byte of 1st register
|
||||
* Index 3: hi-byte of 2nd register
|
||||
* Index 4: low-byte of 2nd register
|
||||
* ...
|
||||
*
|
||||
* @return set of bytes
|
||||
*/
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of registers stored in this instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int size() {
|
||||
return bytes.length / 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (bytes.length == 0) {
|
||||
return "ModbusRegisterArray(<empty>)";
|
||||
}
|
||||
return new StringBuilder(bytes.length).append("ModbusRegisterArray(").append(toHexString()).append(')')
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get register data as a hex string
|
||||
*
|
||||
* For example, 04 45 00 00
|
||||
*
|
||||
* @return string representing the bytes of the register array
|
||||
*/
|
||||
public String toHexString() {
|
||||
if (size() == 0) {
|
||||
return "";
|
||||
}
|
||||
return HexUtils.bytesToHex(getBytes());
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Minimal representation of a modbus response.
|
||||
*
|
||||
* Only function code is exposed, which allows detecting MODBUS exception codes from normal codes.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusResponse {
|
||||
|
||||
/**
|
||||
* Function code of the response.
|
||||
*
|
||||
* Note that in case of Slave responding with Modbus exception response, the response
|
||||
* function code might differ from request function code
|
||||
*
|
||||
* @return function code of the response
|
||||
*/
|
||||
public int getFunctionCode();
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Base interface for callbacks used in Modbus
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusResultCallback {
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Interface for write callbacks
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@NonNullByDefault
|
||||
public interface ModbusWriteCallback extends ModbusResultCallback {
|
||||
|
||||
/**
|
||||
* Callback handling response data
|
||||
*
|
||||
* @param asyncModbusWriteResult result of the write operation
|
||||
*/
|
||||
void handle(AsyncModbusWriteResult result);
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Implementation for writing coils
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusWriteCoilRequestBlueprint extends ModbusWriteRequestBlueprint {
|
||||
|
||||
private static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
private final int slaveId;
|
||||
private final int reference;
|
||||
private final BitArray bits;
|
||||
private final boolean writeMultiple;
|
||||
private final int maxTries;
|
||||
|
||||
/**
|
||||
* Construct coil write request with single bit of data
|
||||
*
|
||||
* @param slaveId slave id to write to
|
||||
* @param reference reference address
|
||||
* @param data bit to write
|
||||
* @param writeMultiple whether to use {@link ModbusWriteFunctionCode.WRITE_MULTIPLE_COILS} over
|
||||
* {@link ModbusWriteFunctionCode.WRITE_COIL}
|
||||
* @param maxTries maximum number of tries in case of errors, should be at least 1
|
||||
*/
|
||||
public ModbusWriteCoilRequestBlueprint(int slaveId, int reference, boolean data, boolean writeMultiple,
|
||||
int maxTries) {
|
||||
this(slaveId, reference, new BitArray(data), writeMultiple, maxTries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct coil write request with many bits of data
|
||||
*
|
||||
* @param slaveId slave id to write to
|
||||
* @param reference reference address
|
||||
* @param data bit(s) to write
|
||||
* @param writeMultiple whether to use {@link ModbusWriteFunctionCode.WRITE_MULTIPLE_COILS} over
|
||||
* {@link ModbusWriteFunctionCode.WRITE_COIL}. Useful with single bit of data.
|
||||
* @param maxTries maximum number of tries in case of errors, should be at least 1
|
||||
* @throws IllegalArgumentException in case <code>data</code> is empty, <code>writeMultiple</code> is
|
||||
* <code>false</code> but there are many bits to write.
|
||||
*/
|
||||
public ModbusWriteCoilRequestBlueprint(int slaveId, int reference, BitArray data, boolean writeMultiple,
|
||||
int maxTries) {
|
||||
super();
|
||||
this.slaveId = slaveId;
|
||||
this.reference = reference;
|
||||
this.bits = data;
|
||||
this.writeMultiple = writeMultiple;
|
||||
this.maxTries = maxTries;
|
||||
|
||||
if (!writeMultiple && bits.size() > 1) {
|
||||
throw new IllegalArgumentException("With multiple coils, writeMultiple must be true");
|
||||
}
|
||||
if (bits.size() == 0) {
|
||||
throw new IllegalArgumentException("Must have at least one bit");
|
||||
}
|
||||
if (maxTries <= 0) {
|
||||
throw new IllegalArgumentException("maxTries should be positive, was " + maxTries);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnitID() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReference() {
|
||||
return reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusWriteFunctionCode getFunctionCode() {
|
||||
return writeMultiple ? ModbusWriteFunctionCode.WRITE_MULTIPLE_COILS : ModbusWriteFunctionCode.WRITE_COIL;
|
||||
}
|
||||
|
||||
public BitArray getCoils() {
|
||||
return bits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxTries() {
|
||||
return maxTries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle).append("slaveId", slaveId).append("reference", reference)
|
||||
.append("functionCode", getFunctionCode()).append("bits", bits).append("maxTries", maxTries).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ModbusWriteRequestBlueprintVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import net.wimpi.modbus.Modbus;
|
||||
|
||||
/**
|
||||
* Modbus write function codes supported by this transport
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
public enum ModbusWriteFunctionCode {
|
||||
WRITE_COIL(Modbus.WRITE_COIL),
|
||||
WRITE_MULTIPLE_COILS(Modbus.WRITE_MULTIPLE_COILS),
|
||||
WRITE_SINGLE_REGISTER(Modbus.WRITE_SINGLE_REGISTER),
|
||||
WRITE_MULTIPLE_REGISTERS(Modbus.WRITE_MULTIPLE_REGISTERS);
|
||||
|
||||
private final int functionCode;
|
||||
|
||||
ModbusWriteFunctionCode(int code) {
|
||||
functionCode = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get numeric function code represented by this instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getFunctionCode() {
|
||||
return functionCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct {@link ModbusWriteFunctionCode} from the numeric function code
|
||||
*
|
||||
* @param functionCode numeric function code
|
||||
* @return {@link ModbusWriteFunctionCode} matching the numeric function code
|
||||
* @throws IllegalArgumentException with unsupported functions
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
public static @NonNull ModbusWriteFunctionCode fromFunctionCode(int functionCode) throws IllegalArgumentException {
|
||||
return Stream.of(ModbusWriteFunctionCode.values()).filter(v -> v.getFunctionCode() == functionCode).findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid functionCode"));
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Implementation for writing registers
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusWriteRegisterRequestBlueprint extends ModbusWriteRequestBlueprint {
|
||||
|
||||
private static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
private final int slaveId;
|
||||
private final int reference;
|
||||
private final ModbusRegisterArray registers;
|
||||
private final boolean writeMultiple;
|
||||
private final int maxTries;
|
||||
|
||||
/**
|
||||
* Construct coil write request with many bits of data
|
||||
*
|
||||
* @param slaveId slave id to write to
|
||||
* @param reference reference address
|
||||
* @param registers register(s) to write
|
||||
* @param writeMultiple whether to use {@link ModbusWriteFunctionCode.WRITE_MULTIPLE_COILS} over
|
||||
* {@link ModbusWriteFunctionCode.WRITE_COIL}. Useful with single register of data.
|
||||
* @param maxTries maximum number of tries in case of errors, should be at least 1
|
||||
* @throws IllegalArgumentException in case <code>data</code> is empty, <code>writeMultiple</code> is
|
||||
* <code>false</code> but there are many registers to write.
|
||||
*/
|
||||
public ModbusWriteRegisterRequestBlueprint(int slaveId, int reference, ModbusRegisterArray registers,
|
||||
boolean writeMultiple, int maxTries) throws IllegalArgumentException {
|
||||
super();
|
||||
this.slaveId = slaveId;
|
||||
this.reference = reference;
|
||||
this.registers = registers;
|
||||
this.writeMultiple = writeMultiple;
|
||||
this.maxTries = maxTries;
|
||||
|
||||
if (!writeMultiple && registers.size() > 1) {
|
||||
throw new IllegalArgumentException("With multiple registers, writeMultiple must be true");
|
||||
}
|
||||
if (registers.size() == 0) {
|
||||
throw new IllegalArgumentException("Must have at least one register");
|
||||
}
|
||||
if (maxTries <= 0) {
|
||||
throw new IllegalArgumentException("maxTries should be positive");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReference() {
|
||||
return reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnitID() {
|
||||
return slaveId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusWriteFunctionCode getFunctionCode() {
|
||||
return writeMultiple ? ModbusWriteFunctionCode.WRITE_MULTIPLE_REGISTERS
|
||||
: ModbusWriteFunctionCode.WRITE_SINGLE_REGISTER;
|
||||
}
|
||||
|
||||
public ModbusRegisterArray getRegisters() {
|
||||
return registers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxTries() {
|
||||
return maxTries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle).append("slaveId", slaveId).append("reference", reference)
|
||||
.append("functionCode", getFunctionCode()).append("registers", registers).append("maxTries", maxTries)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ModbusWriteRequestBlueprintVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import net.wimpi.modbus.Modbus;
|
||||
|
||||
/**
|
||||
* Base interface for Modbus write requests
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class ModbusWriteRequestBlueprint {
|
||||
|
||||
/**
|
||||
* Returns the protocol identifier of this
|
||||
* <tt>ModbusMessage</tt> as <tt>int</tt>.<br>
|
||||
* The identifier is a 2-byte (short) non negative
|
||||
* integer value valid in the range of 0-65535.
|
||||
* <p>
|
||||
*
|
||||
* @return the protocol identifier as <tt>int</tt>.
|
||||
*/
|
||||
public int getProtocolID() {
|
||||
return Modbus.DEFAULT_PROTOCOL_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference of the register/coil/discrete input to to start
|
||||
* writing with this request
|
||||
* <p>
|
||||
*
|
||||
* @return the reference of the register
|
||||
* to start reading from as <tt>int</tt>.
|
||||
*/
|
||||
public abstract int getReference();
|
||||
|
||||
/**
|
||||
* Returns the unit identifier of this
|
||||
* <tt>ModbusMessage</tt> as <tt>int</tt>.<br>
|
||||
* The identifier is a 1-byte non negative
|
||||
* integer value valid in the range of 0-255.
|
||||
* <p>
|
||||
*
|
||||
* @return the unit identifier as <tt>int</tt>.
|
||||
*/
|
||||
public abstract int getUnitID();
|
||||
|
||||
/**
|
||||
* Returns the function code of this
|
||||
* <tt>ModbusMessage</tt> as <tt>int</tt>.<br>
|
||||
* The function code is a 1-byte non negative
|
||||
* integer value valid in the range of 0-127.<br>
|
||||
* Function codes are ordered in conformance
|
||||
* classes their values are specified in
|
||||
* <tt>net.wimpi.modbus.Modbus</tt>.
|
||||
* <p>
|
||||
*
|
||||
* @return the function code as <tt>int</tt>.
|
||||
*
|
||||
* @see net.wimpi.modbus.Modbus
|
||||
*/
|
||||
public abstract ModbusWriteFunctionCode getFunctionCode();
|
||||
|
||||
/**
|
||||
* Get maximum number of tries, in case errors occur. Should be at least 1.
|
||||
*/
|
||||
public abstract int getMaxTries();
|
||||
|
||||
/**
|
||||
* Accept visitor
|
||||
*
|
||||
* @param visitor
|
||||
*/
|
||||
public abstract void accept(ModbusWriteRequestBlueprintVisitor visitor);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ModbusWriteRequestBlueprintVisitor interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusWriteRequestBlueprintVisitor {
|
||||
|
||||
/**
|
||||
* Visit request writing coil data
|
||||
*
|
||||
* @param blueprint
|
||||
*/
|
||||
public void visit(ModbusWriteCoilRequestBlueprint blueprint);
|
||||
|
||||
/**
|
||||
* Visit request writing register data
|
||||
*
|
||||
* @param blueprint
|
||||
*/
|
||||
public void visit(ModbusWriteRegisterRequestBlueprint blueprint);
|
||||
}
|
34
bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/PollTask.java
34
bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/PollTask.java
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Poll task represents Modbus read request
|
||||
*
|
||||
* Must be hashable. HashCode and equals should be defined such that no two poll tasks are registered that are
|
||||
* equal.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
* @see ModbusManager.registerRegularPoll
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface PollTask extends
|
||||
TaskWithEndpoint<ModbusReadRequestBlueprint, ModbusReadCallback, ModbusFailureCallback<ModbusReadRequestBlueprint>> {
|
||||
@Override
|
||||
default int getMaxTries() {
|
||||
return getRequest().getMaxTries();
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Common base interface for read and write tasks.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
* @param <R> request type
|
||||
* @param <C> callback type
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface TaskWithEndpoint<R, C extends ModbusResultCallback, F extends ModbusFailureCallback<R>> {
|
||||
/**
|
||||
* Gets endpoint associated with this task
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ModbusSlaveEndpoint getEndpoint();
|
||||
|
||||
/**
|
||||
* Gets request associated with this task
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
R getRequest();
|
||||
|
||||
/**
|
||||
* Gets the result callback associated with this task, will be called with response
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
C getResultCallback();
|
||||
|
||||
/**
|
||||
* Gets the failure callback associated with this task, will be called in case of an error
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
F getFailureCallback();
|
||||
|
||||
int getMaxTries();
|
||||
}
|
@ -1,331 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.InvalidMarkException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* ByteBuffer-like interface for working with different types of data stored in byte arrays
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ValueBuffer {
|
||||
private final byte[] bytes;
|
||||
private final AtomicInteger byteIndex = new AtomicInteger();
|
||||
private volatile AtomicReference<@Nullable AtomicInteger> mark = new AtomicReference<>();
|
||||
|
||||
/**
|
||||
* Wrap modbus registers and create a new instance of ValueBuffer
|
||||
*
|
||||
* The instance will have position of 0.
|
||||
*
|
||||
* @param array set of registers
|
||||
* @return new instance of ValueBuffer referencing bytes represented by modbus register array
|
||||
*/
|
||||
public static ValueBuffer wrap(ModbusRegisterArray array) {
|
||||
return new ValueBuffer(array.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap given bytes and create a new instance of ValueBuffer
|
||||
*
|
||||
* The instance will have position of 0.
|
||||
*
|
||||
*
|
||||
* @param array set of bytes to wrap
|
||||
* @return new instance of ValueBuffer referencing bytes
|
||||
*/
|
||||
public static ValueBuffer wrap(byte[] array) {
|
||||
return new ValueBuffer(array);
|
||||
}
|
||||
|
||||
private ValueBuffer(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this buffer's position.
|
||||
*
|
||||
* @return The position of this buffer
|
||||
*/
|
||||
public int position() {
|
||||
return byteIndex.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this buffer's position. If the mark is defined and larger than the new position then it is discarded.
|
||||
*
|
||||
* @return this buffer
|
||||
*/
|
||||
public ValueBuffer position(int byteIndex) {
|
||||
this.mark.getAndUpdate(curMark -> {
|
||||
if (curMark == null) {
|
||||
return null;
|
||||
} else if (curMark.get() > byteIndex) {
|
||||
return null;
|
||||
} else {
|
||||
return curMark;
|
||||
}
|
||||
});
|
||||
this.byteIndex.set(byteIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this buffer's mark at its position.
|
||||
*
|
||||
* @return this buffer
|
||||
*/
|
||||
public ValueBuffer mark() {
|
||||
mark = new AtomicReference<>(new AtomicInteger(byteIndex.get()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this buffer's position to the previously-marked position.
|
||||
* Invoking this method neither changes nor discards the mark's value.
|
||||
*
|
||||
* @return this buffer
|
||||
* @throws InvalidMarkException If the mark has not been set
|
||||
*/
|
||||
public ValueBuffer reset() throws InvalidMarkException {
|
||||
int mark = Optional.ofNullable(this.mark.get()).map(i -> i.get()).orElse(-1);
|
||||
if (mark < 0) {
|
||||
throw new InvalidMarkException();
|
||||
}
|
||||
byteIndex.set(mark);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes between the current position and the end.
|
||||
*
|
||||
* @return The number of bytes remaining in this buffer
|
||||
*/
|
||||
public int remaining() {
|
||||
return bytes.length - byteIndex.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns underlying bytes
|
||||
*
|
||||
* @return reference to underlying bytes
|
||||
*/
|
||||
public byte[] array() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether there are any bytes left between current position and the end
|
||||
*
|
||||
* @return true if, and only if, there is at least one byte remaining in this buffer
|
||||
*/
|
||||
public boolean hasRemaining() {
|
||||
return remaining() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting from current position, read dst.length number of bytes and copy the data to dst
|
||||
*
|
||||
* @param dst copied bytes
|
||||
* @return this buffer
|
||||
* @throws BufferOverflowException If there is insufficient space in this buffer for the remaining bytes in the
|
||||
* source buffer
|
||||
*/
|
||||
public ValueBuffer get(byte[] dst) {
|
||||
int start = byteIndex.getAndAdd(dst.length);
|
||||
try {
|
||||
System.arraycopy(bytes, start, dst, 0, dst.length);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 8-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return signed 8-bit integer (byte)
|
||||
* @see ModbusBitUtilities.extractSInt8
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public byte getSInt8() {
|
||||
return ModbusBitUtilities.extractSInt8(bytes, byteIndex.getAndAdd(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 8-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return unsigned 8-bit integer
|
||||
* @see ModbusBitUtilities.extractUInt8
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public short getUInt8() {
|
||||
return ModbusBitUtilities.extractUInt8(bytes, byteIndex.getAndAdd(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 16-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return signed 16-bit integer (short)
|
||||
* @see ModbusBitUtilities.extractSInt16
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public short getSInt16() {
|
||||
return ModbusBitUtilities.extractSInt16(bytes, byteIndex.getAndAdd(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 16-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return unsigned 16-bit integer
|
||||
* @see ModbusBitUtilities.extractUInt16
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public int getUInt16() {
|
||||
return ModbusBitUtilities.extractUInt16(bytes, byteIndex.getAndAdd(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 32-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return signed 32-bit integer
|
||||
* @see ModbusBitUtilities.extractSInt32
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public int getSInt32() {
|
||||
return ModbusBitUtilities.extractSInt32(bytes, byteIndex.getAndAdd(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 32-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return unsigned 32-bit integer
|
||||
* @see ModbusBitUtilities.extractUInt32
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public long getUInt32() {
|
||||
return ModbusBitUtilities.extractUInt32(bytes, byteIndex.getAndAdd(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 32-bit integer at current position, and advance position.
|
||||
*
|
||||
* This is identical with getSInt32, but with registers swapped.
|
||||
*
|
||||
* @return signed 32-bit integer
|
||||
* @see ModbusBitUtilities.extractSInt32Swap
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public int getSInt32Swap() {
|
||||
return ModbusBitUtilities.extractSInt32Swap(bytes, byteIndex.getAndAdd(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 32-bit integer at current position, and advance position.
|
||||
*
|
||||
* This is identical with getUInt32, but with registers swapped.
|
||||
*
|
||||
* @return unsigned 32-bit integer
|
||||
* @see ModbusBitUtilities.extractUInt32Swap
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public long getUInt32Swap() {
|
||||
return ModbusBitUtilities.extractUInt32Swap(bytes, byteIndex.getAndAdd(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 64-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return signed 64-bit integer
|
||||
* @see ModbusBitUtilities.extractInt64
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public long getSInt64() {
|
||||
return ModbusBitUtilities.extractSInt64(bytes, byteIndex.getAndAdd(8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 64-bit integer at current position, and advance position.
|
||||
*
|
||||
* @return unsigned 64-bit integer
|
||||
* @see ModbusBitUtilities.extractUInt64
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public BigInteger getUInt64() {
|
||||
return ModbusBitUtilities.extractUInt64(bytes, byteIndex.getAndAdd(8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract signed 64-bit integer at current position, and advance position.
|
||||
*
|
||||
* This is identical with getSInt64, but with registers swapped.
|
||||
*
|
||||
* @return signed 64-bit integer
|
||||
* @see ModbusBitUtilities.extractInt64Swap
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public long getSInt64Swap() {
|
||||
return ModbusBitUtilities.extractSInt64Swap(bytes, byteIndex.getAndAdd(8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract unsigned 64-bit integer at current position, and advance position.
|
||||
*
|
||||
* This is identical with getUInt64, but with registers swapped.
|
||||
*
|
||||
* @return unsigned 64-bit integer
|
||||
* @see ModbusBitUtilities.extractUInt64Swap
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public BigInteger getUInt64Swap() {
|
||||
return ModbusBitUtilities.extractUInt64Swap(bytes, byteIndex.getAndAdd(8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract single-precision 32-bit IEEE 754 floating point at current position, and advance position.
|
||||
*
|
||||
* Note that this method can return floating point NaN and floating point infinity.
|
||||
*
|
||||
* @return single-precision 32-bit IEEE 754 floating point
|
||||
* @see ModbusBitUtilities.extractFloat32
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public float getFloat32() {
|
||||
return ModbusBitUtilities.extractFloat32(bytes, byteIndex.getAndAdd(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract single-precision 32-bit IEEE 754 floating point at current position, and advance position.
|
||||
*
|
||||
* This is identical with getFloat32, but with registers swapped.
|
||||
*
|
||||
* Note that this method can return floating point NaN and floating point infinity.
|
||||
*
|
||||
* @return single-precision 32-bit IEEE 754 floating point
|
||||
* @see ModbusBitUtilities.extractFloat32
|
||||
* @throws IllegalArgumentException when there are not enough bytes in this ValueBuffer
|
||||
*/
|
||||
public float getFloat32Swap() {
|
||||
return ModbusBitUtilities.extractFloat32Swap(bytes, byteIndex.getAndAdd(4));
|
||||
}
|
||||
}
|
32
bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/WriteTask.java
32
bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/WriteTask.java
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Poll task represents Modbus write request
|
||||
*
|
||||
* Unlike {@link PollTask}, this does not have to be hashable.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface WriteTask extends
|
||||
TaskWithEndpoint<ModbusWriteRequestBlueprint, ModbusWriteCallback, ModbusFailureCallback<ModbusWriteRequestBlueprint>> {
|
||||
@Override
|
||||
default int getMaxTries() {
|
||||
return getRequest().getMaxTries();
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Class representing pooling related configuration of a single endpoint
|
||||
*
|
||||
* This class implements equals hashcode constract, and thus is suitable for use as keys in HashMaps, for example.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EndpointPoolConfiguration {
|
||||
|
||||
/**
|
||||
* How long should be the minimum duration between previous transaction end and the next transaction with the same
|
||||
* endpoint.
|
||||
*
|
||||
* In milliseconds.
|
||||
*/
|
||||
private long interTransactionDelayMillis;
|
||||
|
||||
/**
|
||||
* How long should be the minimum duration between connection-establishments from the pool (with same endpoint). In
|
||||
* milliseconds.
|
||||
*/
|
||||
private long interConnectDelayMillis;
|
||||
|
||||
/**
|
||||
* How many times we want to try connecting to the endpoint before giving up. One means that connection
|
||||
* establishment is tried once.
|
||||
*/
|
||||
private int connectMaxTries = 1;
|
||||
|
||||
/**
|
||||
* Re-connect connection every X milliseconds. Negative means that connection is not disconnected automatically.
|
||||
* One can use 0ms to denote reconnection after every transaction (default).
|
||||
*/
|
||||
private int reconnectAfterMillis;
|
||||
|
||||
/**
|
||||
* How long before we give up establishing the connection. In milliseconds. Default of 0 means that system/OS
|
||||
* default is respected.
|
||||
*/
|
||||
private int connectTimeoutMillis;
|
||||
|
||||
private static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
public long getInterConnectDelayMillis() {
|
||||
return interConnectDelayMillis;
|
||||
}
|
||||
|
||||
public void setInterConnectDelayMillis(long interConnectDelayMillis) {
|
||||
this.interConnectDelayMillis = interConnectDelayMillis;
|
||||
}
|
||||
|
||||
public int getConnectMaxTries() {
|
||||
return connectMaxTries;
|
||||
}
|
||||
|
||||
public void setConnectMaxTries(int connectMaxTries) {
|
||||
this.connectMaxTries = connectMaxTries;
|
||||
}
|
||||
|
||||
public int getReconnectAfterMillis() {
|
||||
return reconnectAfterMillis;
|
||||
}
|
||||
|
||||
public void setReconnectAfterMillis(int reconnectAfterMillis) {
|
||||
this.reconnectAfterMillis = reconnectAfterMillis;
|
||||
}
|
||||
|
||||
public long getInterTransactionDelayMillis() {
|
||||
return interTransactionDelayMillis;
|
||||
}
|
||||
|
||||
public void setInterTransactionDelayMillis(long interTransactionDelayMillis) {
|
||||
this.interTransactionDelayMillis = interTransactionDelayMillis;
|
||||
}
|
||||
|
||||
public int getConnectTimeoutMillis() {
|
||||
return connectTimeoutMillis;
|
||||
}
|
||||
|
||||
public void setConnectTimeoutMillis(int connectTimeoutMillis) {
|
||||
this.connectTimeoutMillis = connectTimeoutMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(2149, 3117).append(interTransactionDelayMillis).append(interConnectDelayMillis)
|
||||
.append(connectMaxTries).append(reconnectAfterMillis).append(connectTimeoutMillis).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle)
|
||||
.append("interTransactionDelayMillis", interTransactionDelayMillis)
|
||||
.append("interConnectDelayMillis", interConnectDelayMillis).append("connectMaxTries", connectMaxTries)
|
||||
.append("reconnectAfterMillis", reconnectAfterMillis)
|
||||
.append("connectTimeoutMillis", connectTimeoutMillis).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
EndpointPoolConfiguration rhs = (EndpointPoolConfiguration) obj;
|
||||
return new EqualsBuilder().append(interTransactionDelayMillis, rhs.interTransactionDelayMillis)
|
||||
.append(interConnectDelayMillis, rhs.interConnectDelayMillis)
|
||||
.append(connectMaxTries, rhs.connectMaxTries).append(reconnectAfterMillis, rhs.reconnectAfterMillis)
|
||||
.append(connectTimeoutMillis, rhs.connectTimeoutMillis).isEquals();
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Common base class for ip based endpoints. Endpoint differentiates different modbus slaves only by the ip address
|
||||
* (string) and port name.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class ModbusIPSlaveEndpoint implements ModbusSlaveEndpoint {
|
||||
|
||||
private String address;
|
||||
private int port;
|
||||
|
||||
private static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
public ModbusIPSlaveEndpoint(String address, int port) {
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// differentiate different protocols using the class name, and after that use address and port
|
||||
int protocolHash = this.getClass().getName().hashCode();
|
||||
if (protocolHash % 2 == 0) {
|
||||
protocolHash += 1;
|
||||
}
|
||||
return new HashCodeBuilder(11, protocolHash).append(address).append(port).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle).append("address", address).append("port", port).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
// different protocol -> not equal!
|
||||
return false;
|
||||
}
|
||||
ModbusIPSlaveEndpoint rhs = (ModbusIPSlaveEndpoint) obj;
|
||||
return new EqualsBuilder().append(address, rhs.address).append(port, rhs.port).isEquals();
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import net.wimpi.modbus.util.SerialParameters;
|
||||
|
||||
/**
|
||||
* Serial endpoint. Endpoint differentiates different modbus slaves only by the serial port.
|
||||
* port.
|
||||
*
|
||||
* Endpoint contains SerialParameters which should be enough to establish the connection.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusSerialSlaveEndpoint implements ModbusSlaveEndpoint {
|
||||
|
||||
private SerialParameters serialParameters;
|
||||
private static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
public ModbusSerialSlaveEndpoint(String portName, int baudRate, int flowControlIn, int flowControlOut, int databits,
|
||||
int stopbits, int parity, String encoding, boolean echo, int receiveTimeoutMillis) {
|
||||
this(new SerialParameters(portName, baudRate, flowControlIn, flowControlOut, databits, stopbits, parity,
|
||||
encoding, echo, receiveTimeoutMillis));
|
||||
}
|
||||
|
||||
public ModbusSerialSlaveEndpoint(String portName, int baudRate, String flowControlIn, String flowControlOut,
|
||||
int databits, String stopbits, String parity, String encoding, boolean echo, int receiveTimeoutMillis) {
|
||||
SerialParameters parameters = new SerialParameters();
|
||||
parameters.setPortName(portName);
|
||||
parameters.setBaudRate(baudRate);
|
||||
parameters.setFlowControlIn(flowControlIn);
|
||||
parameters.setFlowControlOut(flowControlOut);
|
||||
parameters.setDatabits(databits);
|
||||
parameters.setStopbits(stopbits);
|
||||
parameters.setParity(parity);
|
||||
parameters.setEncoding(encoding);
|
||||
parameters.setEcho(echo);
|
||||
parameters.setReceiveTimeoutMillis(receiveTimeoutMillis);
|
||||
this.serialParameters = parameters;
|
||||
}
|
||||
|
||||
private ModbusSerialSlaveEndpoint(SerialParameters serialParameters) {
|
||||
this.serialParameters = serialParameters;
|
||||
}
|
||||
|
||||
public SerialParameters getSerialParameters() {
|
||||
return serialParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R accept(ModbusSlaveEndpointVisitor<R> factory) {
|
||||
return factory.visit(this);
|
||||
}
|
||||
|
||||
public String getPortName() {
|
||||
return serialParameters.getPortName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// hashcode & equal is determined purely by port name
|
||||
return serialParameters.getPortName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
// equals is determined purely by port name
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
ModbusSerialSlaveEndpoint rhs = (ModbusSerialSlaveEndpoint) obj;
|
||||
return new EqualsBuilder().append(serialParameters.getPortName(), rhs.serialParameters.getPortName())
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle).append("portName", serialParameters.getPortName()).toString();
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* ModbusSlaveEndpoint contains minimal connection information to establish connection to the slave. End point equals
|
||||
* and hashCode methods should be implemented such that
|
||||
* they can be used to differentiate different physical slaves. Read and write transactions are processed
|
||||
* one at a time if they are associated with the same endpoint (in the sense of equals and hashCode).
|
||||
*
|
||||
* Note that, endpoint class might not include all configuration that might be necessary to actually
|
||||
* communicate with the slave, just the data that is required to establish the connection.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusSlaveEndpoint {
|
||||
public <R> R accept(ModbusSlaveEndpointVisitor<R> visitor);
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Visitor for ModbusSlaveEndpoint
|
||||
*
|
||||
* @param <R> return type from visit
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface ModbusSlaveEndpointVisitor<R> {
|
||||
|
||||
@Nullable
|
||||
R visit(ModbusTCPSlaveEndpoint endpoint);
|
||||
|
||||
@Nullable
|
||||
R visit(ModbusSerialSlaveEndpoint endpoint);
|
||||
|
||||
@Nullable
|
||||
R visit(ModbusUDPSlaveEndpoint endpoint);
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Endpoint for TCP slaves
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusTCPSlaveEndpoint extends ModbusIPSlaveEndpoint {
|
||||
|
||||
public ModbusTCPSlaveEndpoint(String address, int port) {
|
||||
super(address, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R accept(ModbusSlaveEndpointVisitor<R> factory) {
|
||||
return factory.visit(this);
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.endpoint;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Endpoint for UDP slaves
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusUDPSlaveEndpoint extends ModbusIPSlaveEndpoint {
|
||||
|
||||
public ModbusUDPSlaveEndpoint(String address, int port) {
|
||||
super(address, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R accept(ModbusSlaveEndpointVisitor<R> factory) {
|
||||
return factory.visit(this);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Exception for connection issues
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusConnectionException extends ModbusTransportException {
|
||||
|
||||
private static final long serialVersionUID = -6171226761518661925L;
|
||||
private ModbusSlaveEndpoint endpoint;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param endpoint endpoint associated with this exception
|
||||
*/
|
||||
public ModbusConnectionException(ModbusSlaveEndpoint endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get endpoint associated with this connection error
|
||||
*
|
||||
* @return endpoint with the error
|
||||
*/
|
||||
public ModbusSlaveEndpoint getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getMessage() {
|
||||
return String.format("Error connecting to endpoint %s", endpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ModbusConnectionException(Error connecting to endpoint=%s)", endpoint);
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception for explicit exception responses from Modbus slave
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
* @author Nagy Attila Gabor - added getter for error type
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class ModbusSlaveErrorResponseException extends ModbusTransportException {
|
||||
|
||||
/**
|
||||
* The function code received in the query is not an allowable action for the slave. This may be because the
|
||||
* function code is only applicable to newer devices, and was not implemented in the unit selected. It could also
|
||||
* indicate that the slave is in the wrong state to process a request of this type, for example because it is
|
||||
* unconfigured and is being asked to return register values. If a Poll Program Complete command was issued, this
|
||||
* code indicates that no program function preceded it.
|
||||
*/
|
||||
public static final int ILLEGAL_FUNCTION = 1;
|
||||
|
||||
/**
|
||||
* The data address received in the query is not an allowable address for the slave. More specifically, the
|
||||
* combination of reference number and transfer length is invalid. For a controller with 100 registers, a request
|
||||
* with offset 96 and length 4 would succeed, a request with offset 96 and length 5 will generate exception 02.
|
||||
*/
|
||||
public static final int ILLEGAL_DATA_ACCESS = 2;
|
||||
|
||||
/**
|
||||
* A value contained in the query data field is not an allowable value for the slave. This indicates a fault in the
|
||||
* structure of remainder of a complex request, such as that the implied length is incorrect. It specifically does
|
||||
* NOT mean that a data item submitted for storage in a register has a value outside the expectation of the
|
||||
* application program, since the Modbus protocol is unaware of the significance of any particular value of any
|
||||
* particular register.
|
||||
*/
|
||||
public static final int ILLEGAL_DATA_VALUE = 3;
|
||||
|
||||
/**
|
||||
* An unrecoverable error occurred while the slave was attempting to perform the requested action.
|
||||
*/
|
||||
public static final int SLAVE_DEVICE_FAILURE = 4;
|
||||
|
||||
/**
|
||||
* Specialized use in conjunction with programming commands.
|
||||
* The slave has accepted the request and is processing it, but a long duration of time will be required to do so.
|
||||
* This response is returned to prevent a timeout error from occurring in the master. The master can next issue a
|
||||
* Poll Program Complete message to determine if processing is completed.
|
||||
*/
|
||||
public static final int ACKNOWLEDGE = 5;
|
||||
|
||||
/**
|
||||
* Specialized use in conjunction with programming commands.
|
||||
* The slave is engaged in processing a long-duration program command. The master should retransmit the message
|
||||
* later when the slave is free.
|
||||
*/
|
||||
public static final int SLAVE_DEVICE_BUSY = 6;
|
||||
|
||||
/**
|
||||
* The slave cannot perform the program function received in the query. This code is returned for an unsuccessful
|
||||
* programming request using function code 13 or 14 decimal. The master should request diagnostic or error
|
||||
* information from the slave.
|
||||
*/
|
||||
public static final int NEGATIVE_ACKNOWLEDGE = 7;
|
||||
|
||||
/**
|
||||
* Specialized use in conjunction with function codes 20 and 21 and reference type 6, to indicate that the extended
|
||||
* file area failed to pass a consistency check.
|
||||
* The slave attempted to read extended memory or record file, but detected a parity error in memory. The master can
|
||||
* retry the request, but service may be required on the slave device.
|
||||
*/
|
||||
public static final int MEMORY_PARITY_ERROR = 8;
|
||||
|
||||
/**
|
||||
* Specialized use in conjunction with gateways, indicates that the gateway was unable to allocate an internal
|
||||
* communication path from the input port to the output port for processing the request. Usually means the gateway
|
||||
* is misconfigured or overloaded.
|
||||
*/
|
||||
public static final int GATEWAY_PATH_UNVAVAILABLE = 10;
|
||||
|
||||
/**
|
||||
* Specialized use in conjunction with gateways, indicates that no response was obtained from the target device.
|
||||
* Usually means that the device is not present on the network.
|
||||
*/
|
||||
public static final int GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 11;
|
||||
|
||||
private static final long serialVersionUID = -1435199498550990487L;
|
||||
|
||||
/**
|
||||
* @return the Modbus exception code that happened
|
||||
*/
|
||||
public abstract int getExceptionCode();
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Exception for all IO errors
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusSlaveIOException extends ModbusTransportException {
|
||||
|
||||
private static final long serialVersionUID = -8568199166837844463L;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Base exception for all exceptions in Modbus transport bundle
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusTransportException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1684767401685843339L;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Exception representing situation where function code of the response does not match request
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusUnexpectedResponseFunctionCodeException extends ModbusTransportException {
|
||||
|
||||
private static final long serialVersionUID = 1109165449703638949L;
|
||||
private int requestFunctionCode;
|
||||
private int responseFunctionCode;
|
||||
|
||||
public ModbusUnexpectedResponseFunctionCodeException(int requestFunctionCode, int responseFunctionCode) {
|
||||
this.requestFunctionCode = requestFunctionCode;
|
||||
this.responseFunctionCode = responseFunctionCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getMessage() {
|
||||
return String.format("Function code of request (%d) does not equal response (%d)", requestFunctionCode,
|
||||
responseFunctionCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"ModbusUnexpectedResponseFunctionCodeException(requestFunctionCode=%d, responseFunctionCode=%d)",
|
||||
requestFunctionCode, responseFunctionCode);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Exception representing situation where data length of the response does not match request
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusUnexpectedResponseSizeException extends ModbusTransportException {
|
||||
|
||||
private static final long serialVersionUID = 2460907938819984483L;
|
||||
private int requestSize;
|
||||
private int responseSize;
|
||||
|
||||
public ModbusUnexpectedResponseSizeException(int requestSize, int responseSize) {
|
||||
this.requestSize = requestSize;
|
||||
this.responseSize = responseSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getMessage() {
|
||||
return String.format("Data length of the request (%d) does not equal response (%d). Slave response is invalid.",
|
||||
requestSize, responseSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ModbusUnexpectedResponseSizeException(requestFunctionCode=%d, responseFunctionCode=%d)",
|
||||
requestSize, responseSize);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Exception representing situation where transaction id of the response does not match request
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusUnexpectedTransactionIdException extends ModbusTransportException {
|
||||
|
||||
private static final long serialVersionUID = -2453232634024813933L;
|
||||
private int requestId;
|
||||
private int responseId;
|
||||
|
||||
public ModbusUnexpectedTransactionIdException(int requestId, int responseId) {
|
||||
this.requestId = requestId;
|
||||
this.responseId = responseId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getMessage() {
|
||||
return String.format("Transaction id of request (%d) does not equal response (%d). Slave response is invalid.",
|
||||
requestId, responseId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"ModbusUnexpectedTransactionIdException(requestTransactionId=%d, responseTransactionId=%d)", requestId,
|
||||
responseId);
|
||||
}
|
||||
|
||||
public int getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public int getResponseId() {
|
||||
return responseId;
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Utility for timing operations
|
||||
*
|
||||
* @author Sami Salonen - initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AggregateStopWatch {
|
||||
/**
|
||||
* ID associated with this modbus operation
|
||||
*/
|
||||
final String operationId;
|
||||
|
||||
/**
|
||||
* Total operation time
|
||||
*/
|
||||
final SimpleStopWatch total = new SimpleStopWatch();
|
||||
|
||||
/**
|
||||
* Time for connection related actions
|
||||
*/
|
||||
final SimpleStopWatch connection = new SimpleStopWatch();
|
||||
|
||||
/**
|
||||
* Time for actual the actual transaction (read/write to slave)
|
||||
*/
|
||||
final SimpleStopWatch transaction = new SimpleStopWatch();
|
||||
|
||||
/**
|
||||
* Time for calling calling the callback
|
||||
*/
|
||||
final SimpleStopWatch callback = new SimpleStopWatch();
|
||||
|
||||
public AggregateStopWatch() {
|
||||
this.operationId = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend all running stopwatches of this aggregate
|
||||
*/
|
||||
public void suspendAllRunning() {
|
||||
for (SimpleStopWatch watch : new SimpleStopWatch[] { total, connection, transaction, callback }) {
|
||||
if (watch.isRunning()) {
|
||||
watch.suspend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{total: %d ms, connection: %d, transaction=%d, callback=%d}", total.getTotalTimeMillis(),
|
||||
connection.getTotalTimeMillis(), transaction.getTotalTimeMillis(), callback.getTotalTimeMillis());
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.io.transport.modbus.ModbusFailureCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.PollTask;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Implementation of {@link PollTask} that differentiates tasks using endpoint, request and callbacks.
|
||||
*
|
||||
* Note: Two differentiate poll tasks are considered unequal if their callbacks are unequal.
|
||||
*
|
||||
* HashCode and equals should be defined such that two poll tasks considered the same only if their request,
|
||||
* maxTries, endpoint and callback are the same.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BasicPollTask implements PollTask {
|
||||
|
||||
static StandardToStringStyle toStringStyle = new StandardToStringStyle();
|
||||
static {
|
||||
toStringStyle.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
private ModbusSlaveEndpoint endpoint;
|
||||
private ModbusReadRequestBlueprint request;
|
||||
private ModbusReadCallback resultCallback;
|
||||
private ModbusFailureCallback<ModbusReadRequestBlueprint> failureCallback;
|
||||
|
||||
public BasicPollTask(ModbusSlaveEndpoint endpoint, ModbusReadRequestBlueprint request,
|
||||
ModbusReadCallback resultCallback, ModbusFailureCallback<ModbusReadRequestBlueprint> failureCallback) {
|
||||
this.endpoint = endpoint;
|
||||
this.request = request;
|
||||
this.resultCallback = resultCallback;
|
||||
this.failureCallback = failureCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusReadRequestBlueprint getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusSlaveEndpoint getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusReadCallback getResultCallback() {
|
||||
return resultCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusFailureCallback<ModbusReadRequestBlueprint> getFailureCallback() {
|
||||
return failureCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(69, 5).append(request).append(getEndpoint()).append(getResultCallback())
|
||||
.append(getFailureCallback()).toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, toStringStyle).append("request", request).append("endpoint", endpoint)
|
||||
.append("resultCallback", getResultCallback()).append("failureCallback", getFailureCallback())
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
BasicPollTask rhs = (BasicPollTask) obj;
|
||||
return new EqualsBuilder().append(request, rhs.request).append(endpoint, rhs.endpoint)
|
||||
.append(getResultCallback(), rhs.getResultCallback())
|
||||
.append(getFailureCallback(), rhs.getFailureCallback()).isEquals();
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import org.apache.commons.lang.builder.StandardToStringStyle;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.ModbusFailureCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.WriteTask;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
/**
|
||||
* Simple implementation for Modbus write requests
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BasicWriteTask implements WriteTask {
|
||||
|
||||
private static final StandardToStringStyle TO_STRING_STYLE = new StandardToStringStyle();
|
||||
static {
|
||||
TO_STRING_STYLE.setUseShortClassName(true);
|
||||
}
|
||||
|
||||
private ModbusSlaveEndpoint endpoint;
|
||||
private ModbusWriteRequestBlueprint request;
|
||||
private ModbusWriteCallback resultCallback;
|
||||
private ModbusFailureCallback<ModbusWriteRequestBlueprint> failureCallback;
|
||||
|
||||
public BasicWriteTask(ModbusSlaveEndpoint endpoint, ModbusWriteRequestBlueprint request,
|
||||
ModbusWriteCallback resultCallback, ModbusFailureCallback<ModbusWriteRequestBlueprint> failureCallback) {
|
||||
super();
|
||||
this.endpoint = endpoint;
|
||||
this.request = request;
|
||||
this.resultCallback = resultCallback;
|
||||
this.failureCallback = failureCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusSlaveEndpoint getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusWriteRequestBlueprint getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusWriteCallback getResultCallback() {
|
||||
return resultCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModbusFailureCallback<ModbusWriteRequestBlueprint> getFailureCallback() {
|
||||
return failureCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, TO_STRING_STYLE).append("request", request).append("endpoint", endpoint)
|
||||
.append("resultCallback", resultCallback).append("failureCallback", failureCallback).toString();
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import org.apache.commons.pool2.KeyedPooledObjectFactory;
|
||||
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
|
||||
import net.wimpi.modbus.net.ModbusSlaveConnection;
|
||||
|
||||
/**
|
||||
* Pool for modbus connections.
|
||||
*
|
||||
* Only one connection is allowed to be active at a time.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusConnectionPool extends GenericKeyedObjectPool<ModbusSlaveEndpoint, ModbusSlaveConnection> {
|
||||
|
||||
public ModbusConnectionPool(KeyedPooledObjectFactory<ModbusSlaveEndpoint, ModbusSlaveConnection> factory) {
|
||||
super(factory, new ModbusPoolConfig());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(@Nullable GenericKeyedObjectPoolConfig<ModbusSlaveConnection> conf) {
|
||||
if (conf == null) {
|
||||
return;
|
||||
} else if (!(conf instanceof ModbusPoolConfig)) {
|
||||
throw new IllegalArgumentException("Only ModbusPoolConfig accepted!");
|
||||
}
|
||||
super.setConfig(conf);
|
||||
}
|
||||
}
|
@ -1,347 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.AsyncModbusReadResult;
|
||||
import org.openhab.io.transport.modbus.BitArray;
|
||||
import org.openhab.io.transport.modbus.ModbusReadCallback;
|
||||
import org.openhab.io.transport.modbus.ModbusReadFunctionCode;
|
||||
import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusRegisterArray;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteCoilRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRegisterRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprint;
|
||||
import org.openhab.io.transport.modbus.ModbusWriteRequestBlueprintVisitor;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSerialSlaveEndpoint;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpointVisitor;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusTCPSlaveEndpoint;
|
||||
import org.openhab.io.transport.modbus.endpoint.ModbusUDPSlaveEndpoint;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.wimpi.modbus.io.ModbusSerialTransaction;
|
||||
import net.wimpi.modbus.io.ModbusTCPTransaction;
|
||||
import net.wimpi.modbus.io.ModbusTransaction;
|
||||
import net.wimpi.modbus.io.ModbusUDPTransaction;
|
||||
import net.wimpi.modbus.msg.ModbusRequest;
|
||||
import net.wimpi.modbus.msg.ModbusResponse;
|
||||
import net.wimpi.modbus.msg.ReadCoilsRequest;
|
||||
import net.wimpi.modbus.msg.ReadCoilsResponse;
|
||||
import net.wimpi.modbus.msg.ReadInputDiscretesRequest;
|
||||
import net.wimpi.modbus.msg.ReadInputDiscretesResponse;
|
||||
import net.wimpi.modbus.msg.ReadInputRegistersRequest;
|
||||
import net.wimpi.modbus.msg.ReadInputRegistersResponse;
|
||||
import net.wimpi.modbus.msg.ReadMultipleRegistersRequest;
|
||||
import net.wimpi.modbus.msg.ReadMultipleRegistersResponse;
|
||||
import net.wimpi.modbus.msg.WriteCoilRequest;
|
||||
import net.wimpi.modbus.msg.WriteMultipleCoilsRequest;
|
||||
import net.wimpi.modbus.msg.WriteMultipleRegistersRequest;
|
||||
import net.wimpi.modbus.msg.WriteSingleRegisterRequest;
|
||||
import net.wimpi.modbus.net.ModbusSlaveConnection;
|
||||
import net.wimpi.modbus.net.SerialConnection;
|
||||
import net.wimpi.modbus.net.TCPMasterConnection;
|
||||
import net.wimpi.modbus.net.UDPMasterConnection;
|
||||
import net.wimpi.modbus.procimg.InputRegister;
|
||||
import net.wimpi.modbus.procimg.Register;
|
||||
import net.wimpi.modbus.procimg.SimpleInputRegister;
|
||||
import net.wimpi.modbus.util.BitVector;
|
||||
|
||||
/**
|
||||
* Conversion utilities between underlying Modbus library (net.wimpi.modbus) and this transport bundle
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusLibraryWrapper {
|
||||
|
||||
private static Logger getLogger() {
|
||||
return LoggerFactory.getLogger(ModbusLibraryWrapper.class);
|
||||
}
|
||||
|
||||
private static BitArray bitArrayFromBitVector(BitVector bitVector, int count) {
|
||||
boolean[] bits = new boolean[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
bits[i] = bitVector.getBit(i);
|
||||
}
|
||||
return new BitArray(bits);
|
||||
}
|
||||
|
||||
private static ModbusRegisterArray modbusRegisterArrayFromInputRegisters(InputRegister[] inputRegisters) {
|
||||
int[] registers = new int[inputRegisters.length];
|
||||
for (int i = 0; i < inputRegisters.length; i++) {
|
||||
registers[i] = inputRegisters[i].getValue();
|
||||
}
|
||||
return new ModbusRegisterArray(registers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the general request to Modbus library request object
|
||||
*
|
||||
* @param message
|
||||
* @throws IllegalArgumentException
|
||||
* 1) in case function code implies coil data but we have registers
|
||||
* 2) in case function code implies register data but we have coils
|
||||
* 3) in case there is no data
|
||||
* 4) in case there is too much data in case of WRITE_COIL or WRITE_SINGLE_REGISTER
|
||||
* @throws IllegalStateException unexpected function code. Implementation is lacking and this can be considered a
|
||||
* bug
|
||||
* @return MODBUS library request matching the write request
|
||||
*/
|
||||
public static ModbusRequest createRequest(ModbusWriteRequestBlueprint message) {
|
||||
// ModbusRequest[] request = new ModbusRequest[1];
|
||||
AtomicReference<ModbusRequest> request = new AtomicReference<>();
|
||||
AtomicBoolean writeSingle = new AtomicBoolean(false);
|
||||
switch (message.getFunctionCode()) {
|
||||
case WRITE_COIL:
|
||||
writeSingle.set(true);
|
||||
// fall-through on purpose
|
||||
case WRITE_MULTIPLE_COILS:
|
||||
message.accept(new ModbusWriteRequestBlueprintVisitor() {
|
||||
|
||||
@Override
|
||||
public void visit(ModbusWriteRegisterRequestBlueprint blueprint) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModbusWriteCoilRequestBlueprint blueprint) {
|
||||
BitArray coils = blueprint.getCoils();
|
||||
if (coils.size() == 0) {
|
||||
throw new IllegalArgumentException("Must provide at least one coil");
|
||||
}
|
||||
if (writeSingle.get()) {
|
||||
if (coils.size() != 1) {
|
||||
throw new IllegalArgumentException("Must provide single coil with WRITE_COIL");
|
||||
}
|
||||
request.set(new WriteCoilRequest(message.getReference(), coils.getBit(0)));
|
||||
} else {
|
||||
request.set(new WriteMultipleCoilsRequest(message.getReference(),
|
||||
ModbusLibraryWrapper.convertBits(coils)));
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case WRITE_SINGLE_REGISTER:
|
||||
writeSingle.set(true);
|
||||
// fall-through on purpose
|
||||
case WRITE_MULTIPLE_REGISTERS:
|
||||
message.accept(new ModbusWriteRequestBlueprintVisitor() {
|
||||
|
||||
@Override
|
||||
public void visit(ModbusWriteRegisterRequestBlueprint blueprint) {
|
||||
Register[] registers = ModbusLibraryWrapper.convertRegisters(blueprint.getRegisters());
|
||||
if (registers.length == 0) {
|
||||
throw new IllegalArgumentException("Must provide at least one register");
|
||||
}
|
||||
if (writeSingle.get()) {
|
||||
if (blueprint.getRegisters().size() != 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Must provide single register with WRITE_SINGLE_REGISTER");
|
||||
}
|
||||
request.set(new WriteSingleRegisterRequest(message.getReference(), registers[0]));
|
||||
} else {
|
||||
request.set(new WriteMultipleRegistersRequest(message.getReference(), registers));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModbusWriteCoilRequestBlueprint blueprint) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
getLogger().error("Unexpected function code {}", message.getFunctionCode());
|
||||
throw new IllegalStateException(
|
||||
String.format("Unexpected function code %s", message.getFunctionCode()));
|
||||
}
|
||||
ModbusRequest modbusRequest = request.get();
|
||||
modbusRequest.setUnitID(message.getUnitID());
|
||||
modbusRequest.setProtocolID(message.getProtocolID());
|
||||
return modbusRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fresh transaction for the given endpoint and connection
|
||||
*
|
||||
* The retries of the transaction will be disabled.
|
||||
*
|
||||
* @param endpoint
|
||||
* @param connection
|
||||
* @return
|
||||
*/
|
||||
public static ModbusTransaction createTransactionForEndpoint(ModbusSlaveEndpoint endpoint,
|
||||
ModbusSlaveConnection connection) {
|
||||
ModbusTransaction transaction = endpoint.accept(new ModbusSlaveEndpointVisitor<ModbusTransaction>() {
|
||||
|
||||
@Override
|
||||
public @NonNull ModbusTransaction visit(ModbusTCPSlaveEndpoint modbusIPSlavePoolingKey) {
|
||||
ModbusTCPTransaction transaction = new ModbusTCPTransaction();
|
||||
transaction.setReconnecting(false);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ModbusTransaction visit(ModbusSerialSlaveEndpoint modbusSerialSlavePoolingKey) {
|
||||
return new ModbusSerialTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ModbusTransaction visit(ModbusUDPSlaveEndpoint modbusUDPSlavePoolingKey) {
|
||||
return new ModbusUDPTransaction();
|
||||
}
|
||||
});
|
||||
// We disable modbus library retries and handle in the Manager implementation
|
||||
transaction.setRetries(0);
|
||||
transaction.setRetryDelayMillis(0);
|
||||
if (transaction instanceof ModbusSerialTransaction) {
|
||||
((ModbusSerialTransaction) transaction).setSerialConnection((SerialConnection) connection);
|
||||
} else if (transaction instanceof ModbusUDPTransaction) {
|
||||
((ModbusUDPTransaction) transaction).setTerminal(((UDPMasterConnection) connection).getTerminal());
|
||||
} else if (transaction instanceof ModbusTCPTransaction) {
|
||||
((ModbusTCPTransaction) transaction).setConnection((TCPMasterConnection) connection);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create fresh request corresponding to {@link ModbusReadRequestBlueprint}
|
||||
*
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public static ModbusRequest createRequest(ModbusReadRequestBlueprint message) {
|
||||
ModbusRequest request;
|
||||
if (message.getFunctionCode() == ModbusReadFunctionCode.READ_COILS) {
|
||||
request = new ReadCoilsRequest(message.getReference(), message.getDataLength());
|
||||
} else if (message.getFunctionCode() == ModbusReadFunctionCode.READ_INPUT_DISCRETES) {
|
||||
request = new ReadInputDiscretesRequest(message.getReference(), message.getDataLength());
|
||||
} else if (message.getFunctionCode() == ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS) {
|
||||
request = new ReadMultipleRegistersRequest(message.getReference(), message.getDataLength());
|
||||
} else if (message.getFunctionCode() == ModbusReadFunctionCode.READ_INPUT_REGISTERS) {
|
||||
request = new ReadInputRegistersRequest(message.getReference(), message.getDataLength());
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Unexpected function code %s", message.getFunctionCode()));
|
||||
}
|
||||
request.setUnitID(message.getUnitID());
|
||||
request.setProtocolID(message.getProtocolID());
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link BitArray} to {@link BitVector}
|
||||
*
|
||||
* @param bits
|
||||
* @return
|
||||
*/
|
||||
public static BitVector convertBits(BitArray bits) {
|
||||
BitVector bitVector = new BitVector(bits.size());
|
||||
IntStream.range(0, bits.size()).forEach(i -> bitVector.setBit(i, bits.getBit(i)));
|
||||
return bitVector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link ModbusRegisterArray} to array of {@link Register}
|
||||
*
|
||||
* @param bits
|
||||
* @return
|
||||
*/
|
||||
public static Register[] convertRegisters(ModbusRegisterArray arr) {
|
||||
return IntStream.range(0, arr.size()).mapToObj(i -> new SimpleInputRegister(arr.getRegister(i)))
|
||||
.collect(Collectors.toList()).toArray(new Register[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of bits/registers/discrete inputs in the request.
|
||||
*
|
||||
*
|
||||
* @param response
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static int getNumberOfItemsInResponse(ModbusResponse response, ModbusReadRequestBlueprint request) {
|
||||
// jamod library seems to be a bit buggy when it comes number of coils/discrete inputs in the response. Some
|
||||
// of the methods such as ReadCoilsResponse.getBitCount() are returning wrong values.
|
||||
//
|
||||
// This is the reason we use a bit more verbose way to get the number of items in the response.
|
||||
final int responseCount;
|
||||
if (request.getFunctionCode() == ModbusReadFunctionCode.READ_COILS) {
|
||||
responseCount = ((ReadCoilsResponse) response).getCoils().size();
|
||||
} else if (request.getFunctionCode() == ModbusReadFunctionCode.READ_INPUT_DISCRETES) {
|
||||
responseCount = ((ReadInputDiscretesResponse) response).getDiscretes().size();
|
||||
} else if (request.getFunctionCode() == ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS) {
|
||||
responseCount = ((ReadMultipleRegistersResponse) response).getRegisters().length;
|
||||
} else if (request.getFunctionCode() == ModbusReadFunctionCode.READ_INPUT_REGISTERS) {
|
||||
responseCount = ((ReadInputRegistersResponse) response).getRegisters().length;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Unexpected function code %s", request.getFunctionCode()));
|
||||
}
|
||||
return responseCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke callback with the data received
|
||||
*
|
||||
* @param message original request
|
||||
* @param callback callback for read
|
||||
* @param response Modbus library response object
|
||||
*/
|
||||
public static void invokeCallbackWithResponse(ModbusReadRequestBlueprint request, ModbusReadCallback callback,
|
||||
ModbusResponse response) {
|
||||
try {
|
||||
getLogger().trace("Calling read response callback {} for request {}. Response was {}", callback, request,
|
||||
response);
|
||||
// The number of coils/discrete inputs received in response are always in the multiples of 8
|
||||
// bits.
|
||||
// So even if querying 5 bits, you will actually get 8 bits. Here we wrap the data in
|
||||
// BitArrayWrappingBitVector
|
||||
// with will validate that the consumer is not accessing the "invalid" bits of the response.
|
||||
int dataItemsInResponse = getNumberOfItemsInResponse(response, request);
|
||||
if (request.getFunctionCode() == ModbusReadFunctionCode.READ_COILS) {
|
||||
BitVector bits = ((ReadCoilsResponse) response).getCoils();
|
||||
BitArray payload = bitArrayFromBitVector(bits, Math.min(dataItemsInResponse, request.getDataLength()));
|
||||
callback.handle(new AsyncModbusReadResult(request, payload));
|
||||
} else if (request.getFunctionCode() == ModbusReadFunctionCode.READ_INPUT_DISCRETES) {
|
||||
BitVector bits = ((ReadInputDiscretesResponse) response).getDiscretes();
|
||||
BitArray payload = bitArrayFromBitVector(bits, Math.min(dataItemsInResponse, request.getDataLength()));
|
||||
callback.handle(new AsyncModbusReadResult(request, payload));
|
||||
} else if (request.getFunctionCode() == ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS) {
|
||||
ModbusRegisterArray payload = modbusRegisterArrayFromInputRegisters(
|
||||
((ReadMultipleRegistersResponse) response).getRegisters());
|
||||
callback.handle(new AsyncModbusReadResult(request, payload));
|
||||
} else if (request.getFunctionCode() == ModbusReadFunctionCode.READ_INPUT_REGISTERS) {
|
||||
ModbusRegisterArray payload = modbusRegisterArrayFromInputRegisters(
|
||||
((ReadInputRegistersResponse) response).getRegisters());
|
||||
callback.handle(new AsyncModbusReadResult(request, payload));
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unexpected function code %s", request.getFunctionCode()));
|
||||
}
|
||||
} finally {
|
||||
getLogger().trace("Called read response callback {} for request {}. Response was {}", callback, request,
|
||||
response);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import org.apache.commons.pool2.impl.DefaultEvictionPolicy;
|
||||
import org.apache.commons.pool2.impl.EvictionPolicy;
|
||||
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.io.transport.modbus.internal.pooling.ModbusSlaveConnectionEvictionPolicy;
|
||||
|
||||
import net.wimpi.modbus.net.ModbusSlaveConnection;
|
||||
|
||||
/**
|
||||
* Configuration for Modbus connection pool
|
||||
*
|
||||
* Default is that
|
||||
* - there is only one connection per endpoint
|
||||
* - clients are served "fairly" (first-come-first-serve)
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusPoolConfig extends GenericKeyedObjectPoolConfig<ModbusSlaveConnection> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private EvictionPolicy<ModbusSlaveConnection> evictionPolicy = new DefaultEvictionPolicy<>();
|
||||
|
||||
public ModbusPoolConfig() {
|
||||
// When the pool is exhausted, multiple calling threads may be simultaneously blocked waiting for instances
|
||||
// to
|
||||
// become available. As of pool 1.5, a "fairness" algorithm has been implemented to ensure that threads
|
||||
// receive
|
||||
// available instances in request arrival order.
|
||||
setFairness(true);
|
||||
|
||||
// Limit one connection per endpoint (i.e. same ip:port pair or same serial device).
|
||||
// If there are multiple read/write requests to process at the same time, block until previous one finishes
|
||||
setBlockWhenExhausted(true);
|
||||
setMaxTotalPerKey(1);
|
||||
|
||||
// block infinitely when exhausted
|
||||
setMaxWaitMillis(-1);
|
||||
|
||||
// Connections are "tested" on return. Effectively, disconnected connections are destroyed when returning on
|
||||
// pool
|
||||
// Note that we do not test on borrow -- that would mean blocking situation when connection cannot be
|
||||
// established.
|
||||
// Instead, borrowing connection from pool can return unconnected connection.
|
||||
setTestOnReturn(true);
|
||||
|
||||
// disable JMX
|
||||
setJmxEnabled(false);
|
||||
|
||||
// Evict idle connections every 10 seconds
|
||||
setEvictionPolicy(new ModbusSlaveConnectionEvictionPolicy());
|
||||
setTimeBetweenEvictionRunsMillis(10000);
|
||||
// Let eviction re-create ready-to-use idle (=unconnected) connections
|
||||
// This is to avoid occasional / rare deadlocks seen with pool 2.8.1 & 2.4.3 when
|
||||
// borrow hangs (waiting indefinitely for idle object to appear in the pool)
|
||||
// https://github.com/openhab/openhab-addons/issues/8460
|
||||
setMinIdlePerKey(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEvictionPolicyClassName(@Nullable String evictionPolicyClassName) {
|
||||
// Protect against https://issues.apache.org/jira/browse/POOL-338
|
||||
// Disallow re-setting eviction policy with class name. Only setEvictionPolicy allowed
|
||||
throw new IllegalStateException("setEvictionPolicyClassName disallowed! Will fail in OSGI");
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.io.transport.modbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.io.transport.modbus.ModbusResponse;
|
||||
|
||||
import net.wimpi.modbus.msg.ModbusMessage;
|
||||
|
||||
/**
|
||||
* Basic implementation of {@link ModbusResponse}
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ModbusResponseImpl implements ModbusResponse {
|
||||
|
||||
private int responseFunctionCode;
|
||||
|
||||
public ModbusResponseImpl(ModbusMessage response) {
|
||||
super();
|
||||
this.responseFunctionCode = response.getFunctionCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFunctionCode() {
|
||||
return responseFunctionCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ModbusResponseImpl(responseFC=%d)", responseFunctionCode);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user