mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[modbus] Added support for RTU encoding over TCP (#9435)
* [modbus] add support for rtu encoded over tcp * [modbus] move classes to openhab/jamod * [modbus] spotless * [modbus] revert EndpointPoolConfiguration * [modbus] remove virtual serial * [modbus] resolve dependencies * [modbus.studer] add support for RTU over TCP bridge Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This commit is contained in:
parent
6cb9f3a93e
commit
aebe1d4a0b
@ -114,6 +114,11 @@ All channels read for a VarioString device
|
||||
|
||||
```
|
||||
Bridge modbus:serial:bridge [port="/dev/ttyUSB0",baud=9600,dataBits=8,parity="even",stopBits="1.0",encoding="rtu"]
|
||||
..or..
|
||||
Bridge modbus:tcp:bridge [host="192.168.178.56", port=502, rtuEncoded=true]
|
||||
|
||||
...
|
||||
|
||||
Thing modbus:xtender:bridge:xtenderdevice "Xtender" (modbus:serial:modbusbridge) [ slaveAddress=10, refresh=5 ]
|
||||
```
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
<thing-type id="bsp">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="serial"/>
|
||||
<bridge-type-ref id="tcp"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>BSP Studer</label>
|
||||
<description>Thing for Studer BSP Device</description>
|
||||
|
@ -37,8 +37,8 @@ The binding can also *write* data to Modbus slaves using FC05 (Write single coil
|
||||
|
||||
Please note the following caveats or limitations
|
||||
|
||||
* the binding does *not* act as Modbus slave (e.g. as Modbus TCP server).
|
||||
* the binding does *not* support Modbus RTU over Modbus TCP, also known as "Modbus over TCP/IP" or "Modbus over TCP" or "Modbus RTU/IP", although normal "Modbus TCP" is supported. However, there is a workaround: you can use a Virtual Serial Port Server, to emulate a COM Port and Bind it with openHAB using Modbus Serial.
|
||||
* The binding does *not* act as Modbus slave (e.g. as Modbus TCP server).
|
||||
* The binding *does* support Modbus RTU over Modbus TCP, (also known as "Modbus over TCP/IP" or "Modbus over TCP" or "Modbus RTU/IP"), as well as normal "Modbus TCP".
|
||||
|
||||
|
||||
## Background Material
|
||||
@ -108,11 +108,12 @@ When optional parameters are not specified, they default to the values shown in
|
||||
|
||||
Basic parameters
|
||||
|
||||
| Parameter | Type | Required | Default if omitted | Description |
|
||||
| --------- | ------- | -------- | ------------------ | ----------------------------------------------------------- |
|
||||
| `host` | text | | `"localhost"` | IP Address or hostname |
|
||||
| `port` | integer | | `502` | Port number |
|
||||
| `id` | integer | | `1` | Slave id. Also known as station address or unit identifier. |
|
||||
| Parameter | Type | Required | Default if omitted | Description |
|
||||
| ------------ | ------- | -------- | ------------------ | ----------------------------------------------------------- |
|
||||
| `host` | text | | `"localhost"` | IP Address or hostname |
|
||||
| `port` | integer | | `502` | Port number |
|
||||
| `id` | integer | | `1` | Slave id. Also known as station address or unit identifier. |
|
||||
| `rtuEncoded` | boolean | | `false` | Use RTU encoding instead of regular TCP encoding. |
|
||||
|
||||
Advanced parameters
|
||||
|
||||
|
@ -32,6 +32,11 @@ public class ModbusTcpConfiguration {
|
||||
private int reconnectAfterMillis;
|
||||
private int connectTimeoutMillis;
|
||||
private boolean enableDiscovery;
|
||||
private boolean rtuEncoded;
|
||||
|
||||
public boolean getRtuEncoded() {
|
||||
return rtuEncoded;
|
||||
}
|
||||
|
||||
public @Nullable String getHost() {
|
||||
return host;
|
||||
|
@ -51,7 +51,7 @@ public class ModbusTcpThingHandler
|
||||
}
|
||||
|
||||
this.config = config;
|
||||
endpoint = new ModbusTCPSlaveEndpoint(host, config.getPort());
|
||||
endpoint = new ModbusTCPSlaveEndpoint(host, config.getPort(), config.getRtuEncoded());
|
||||
|
||||
EndpointPoolConfiguration poolConfiguration = new EndpointPoolConfiguration();
|
||||
this.poolConfiguration = poolConfiguration;
|
||||
|
@ -32,6 +32,12 @@
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="rtuEncoded" type="boolean">
|
||||
<label>RTU Encoding</label>
|
||||
<description>Use RTU Encoding over IP</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<!-- connection handling -->
|
||||
<parameter name="timeBetweenTransactionsMillis" type="integer" min="0" unit="ms">
|
||||
<label>Time Between Transactions</label>
|
||||
|
@ -20,8 +20,13 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.openhab.binding.modbus.internal.ModbusBindingConstantsInternal.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
@ -151,7 +156,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
}
|
||||
|
||||
private Bridge createTcpMock() {
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
Bridge tcpBridge = ModbusPollerThingHandlerTest.createTcpThingBuilder("tcp1").build();
|
||||
ModbusTcpThingHandler tcpThingHandler = Mockito.mock(ModbusTcpThingHandler.class);
|
||||
tcpBridge.setStatusInfo(new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, ""));
|
||||
@ -257,7 +262,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
private void testOutOfBoundsGeneric(int pollStart, int pollLength, String start,
|
||||
ModbusReadFunctionCode functionCode, ValueType valueType, ThingStatus expectedStatus,
|
||||
BundleContext context) {
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
|
||||
// Minimally mocked request
|
||||
ModbusReadRequestBlueprint request = Mockito.mock(ModbusReadRequestBlueprint.class);
|
||||
@ -409,7 +414,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
private ModbusDataThingHandler testReadHandlingGeneric(ModbusReadFunctionCode functionCode, String start,
|
||||
String transform, ValueType valueType, BitArray bits, ModbusRegisterArray registers, Exception error,
|
||||
BundleContext context, boolean autoCreateItemsAndLinkToChannels) {
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
|
||||
int pollLength = 3;
|
||||
|
||||
@ -461,7 +466,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
private ModbusDataThingHandler testWriteHandlingGeneric(String start, String transform, ValueType valueType,
|
||||
String writeType, ModbusWriteFunctionCode successFC, String channel, Command command, Exception error,
|
||||
BundleContext context) {
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
|
||||
// Minimally mocked request
|
||||
ModbusReadRequestBlueprint request = Mockito.mock(ModbusReadRequestBlueprint.class);
|
||||
@ -716,7 +721,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
|
||||
private void testValueTypeGeneric(ModbusReadFunctionCode functionCode, ValueType valueType,
|
||||
ThingStatus expectedStatus) {
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
|
||||
// Minimally mocked request
|
||||
ModbusReadRequestBlueprint request = Mockito.mock(ModbusReadRequestBlueprint.class);
|
||||
@ -764,7 +769,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
public void testRefreshOnData() throws InterruptedException {
|
||||
ModbusReadFunctionCode functionCode = ModbusReadFunctionCode.READ_COILS;
|
||||
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
|
||||
int pollLength = 3;
|
||||
|
||||
@ -817,7 +822,7 @@ public class ModbusDataHandlerTest extends AbstractModbusOSGiTest {
|
||||
ThingHandler foo = parent.getHandler();
|
||||
addThing(parent);
|
||||
} else {
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502);
|
||||
ModbusSlaveEndpoint endpoint = new ModbusTCPSlaveEndpoint("thisishost", 502, false);
|
||||
|
||||
// Minimally mocked request
|
||||
ModbusReadRequestBlueprint request = Mockito.mock(ModbusReadRequestBlueprint.class);
|
||||
|
@ -276,7 +276,7 @@ public class ModbusPollerThingHandlerTest extends AbstractModbusOSGiTest {
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private boolean checkEndpoint(ModbusSlaveEndpoint endpointParam) {
|
||||
return endpointParam.equals(new ModbusTCPSlaveEndpoint(HOST, PORT));
|
||||
return endpointParam.equals(new ModbusTCPSlaveEndpoint(HOST, PORT, false));
|
||||
}
|
||||
|
||||
private boolean checkRequest(ModbusReadRequestBlueprint request, ModbusReadFunctionCode functionCode) {
|
||||
|
@ -70,7 +70,7 @@ public class ModbusTcpThingHandlerTest extends AbstractModbusOSGiTest {
|
||||
ModbusTcpThingHandler thingHandler = (ModbusTcpThingHandler) thing.getHandler();
|
||||
assertNotNull(thingHandler);
|
||||
ModbusSlaveEndpoint slaveEndpoint = thingHandler.getEndpoint();
|
||||
assertThat(slaveEndpoint, is(equalTo(new ModbusTCPSlaveEndpoint("thisishost", 44))));
|
||||
assertThat(slaveEndpoint, is(equalTo(new ModbusTCPSlaveEndpoint("thisishost", 44, false))));
|
||||
assertThat(thingHandler.getSlaveId(), is(9));
|
||||
|
||||
InOrder orderedVerify = Mockito.inOrder(mockedModbusManager);
|
||||
|
Loading…
Reference in New Issue
Block a user