Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for unit-id option for modbus tags. #1464

Merged
merged 1 commit into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
- `serial`
5+|Config options:
|`request-timeout` |INT |5000| |Default timeout for all types of requests.
|`unit-identifier` |INT |1| |Unit-identifier that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.
|`default-unit-identifier` |STRUCT |1| |Unit-identifier or slave-id that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.
5+|Transport config options:
5+|
+++
Expand Down
2 changes: 1 addition & 1 deletion plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
- `serial`
5+|Config options:
|`request-timeout` |INT |5000| |Default timeout for all types of requests.
|`unit-identifier` |INT |1| |Unit-identifier that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.
|`default-unit-identifier` |INT |1| |Unit-identifier or slave-id that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.
5+|Transport config options:
5+|
+++
Expand Down
2 changes: 1 addition & 1 deletion plc4j/drivers/all/src/site/generated/modbus-tcp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
- `tcp`
5+|Config options:
|`request-timeout` |INT |5000| |Default timeout for all types of requests.
|`unit-identifier` |INT |1| |Unit-identifier that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.
|`default-unit-identifier` |INT |1| |Unit-identifier or slave-id that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.
|`ping-address` |STRING |4x00001:BOOL| |Simple address, that the driver will use to check, if the connection to a given device is active (Defaults to reading holding-register 1).
5+|Transport config options:
5+|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ public class ModbusAsciiConfiguration implements PlcConnectionConfiguration {
@Description("Default timeout for all types of requests.")
private int requestTimeout;

@ConfigurationParameter("unit-identifier")
@ConfigurationParameter("default-unit-identifier")
@IntDefaultValue(1)
@Description("Unit-identifier or slave-id that identifies the target PLC (On RS485 multiple Modbus Devices can be listening). Defaults to 1.")
private int unitIdentifier;
private short defaultUnitIdentifier;

public int getRequestTimeout() {
return requestTimeout;
Expand All @@ -43,19 +43,19 @@ public void setRequestTimeout(int requestTimeout) {
this.requestTimeout = requestTimeout;
}

public int getUnitIdentifier() {
return unitIdentifier;
public short getDefaultUnitIdentifier() {
return defaultUnitIdentifier;
}

public void setUnitIdentifier(int unitIdentifier) {
this.unitIdentifier = unitIdentifier;
public void setDefaultUnitIdentifier(short defaultUnitIdentifier) {
this.defaultUnitIdentifier = defaultUnitIdentifier;
}

@Override
public String toString() {
return "ModbusAsciiConfiguration{" +
"requestTimeout=" + requestTimeout +
", unitIdentifier=" + unitIdentifier +
", defaultUnitIdentifier=" + defaultUnitIdentifier +
'}';
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public ModbusAsciiProtocolLogic() {
@Override
public void setConfiguration(ModbusAsciiConfiguration configuration) {
this.requestTimeout = Duration.ofMillis(configuration.getRequestTimeout());
this.unitIdentifier = (short) configuration.getUnitIdentifier();
this.unitIdentifier = configuration.getDefaultUnitIdentifier();
this.tm = new RequestTransactionManager(1);
}

Expand All @@ -64,7 +64,8 @@ public CompletableFuture<PlcPingResponse> ping(PlcPingRequest pingRequest) {
// So we fall back to a request, that most certainly is implemented by any device. Even if the device doesn't
// have any holding-register:1, it should still gracefully respond.
ModbusPDU readRequestPdu = getReadRequestPdu(pingAddress);
ModbusAsciiADU modbusTcpADU = new ModbusAsciiADU(unitIdentifier, readRequestPdu);
short unitId = getUnitId(pingAddress);
ModbusAsciiADU modbusTcpADU = new ModbusAsciiADU(unitId, readRequestPdu);

RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusTcpADU)
Expand Down Expand Up @@ -99,8 +100,9 @@ public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
String tagName = request.getTagNames().iterator().next();
ModbusTag tag = (ModbusTag) request.getTag(tagName);
final ModbusPDU requestPdu = getReadRequestPdu(tag);
final short unitId = getUnitId(tag);

ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitIdentifier, requestPdu);
ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitId, requestPdu);
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusAsciiADU)
.expectResponse(ModbusAsciiADU.class, requestTimeout)
Expand Down Expand Up @@ -158,7 +160,8 @@ public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
String tagName = request.getTagNames().iterator().next();
PlcTag tag = request.getTag(tagName);
final ModbusPDU requestPdu = getWriteRequestPdu(tag, writeRequest.getPlcValue(tagName));
ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitIdentifier, requestPdu);
final short unitId = getUnitId(tag);
ModbusAsciiADU modbusAsciiADU = new ModbusAsciiADU(unitId, requestPdu);
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(modbusAsciiADU)
.expectResponse(ModbusAsciiADU.class, requestTimeout)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@
package org.apache.plc4x.java.modbus.base.protocol;

import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.PlcPingRequest;
import org.apache.plc4x.java.api.messages.PlcPingResponse;
import org.apache.plc4x.java.api.messages.PlcReadResponse;
import org.apache.plc4x.java.api.model.PlcTag;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.api.types.PlcResponseCode;
Expand All @@ -40,7 +37,6 @@
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class ModbusProtocolLogic<T extends ModbusADU> extends Plc4xProtocolBase<T> {
Expand Down Expand Up @@ -97,6 +93,15 @@ protected PlcResponseCode getErrorCode(ModbusPDUError errorResponse) {
}
}

protected short getUnitId(PlcTag tag) {
if (tag instanceof ModbusTag) {
Short unitId = ((ModbusTag) tag).getUnitId();
return unitId == null ? unitIdentifier : unitId;
}

return unitIdentifier;
}

protected ModbusPDU getReadRequestPdu(PlcTag tag) {
if (tag instanceof ModbusTagDiscreteInput) {
ModbusTagDiscreteInput discreteInput = (ModbusTagDiscreteInput) tag;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
import org.apache.plc4x.java.spi.utils.Serializable;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.regex.Pattern;

public abstract class ModbusTag implements PlcTag, Serializable {
Expand All @@ -47,6 +45,7 @@ public abstract class ModbusTag implements PlcTag, Serializable {
private final int quantity;

private final ModbusDataType dataType;
private final Short unitId;

public static ModbusTag of(String addressString) {
if (ModbusTagCoil.matches(addressString)) {
Expand Down Expand Up @@ -88,6 +87,10 @@ public String getAddressString() {
* @param dataType The type for the interpretation of the registers.
*/
protected ModbusTag(int address, Integer quantity, ModbusDataType dataType) {
this(address, quantity, dataType, new HashMap<>());
}

protected ModbusTag(int address, Integer quantity, ModbusDataType dataType, Map<String, String> config) {
this.address = address;
if (getLogicalAddress() <= 0) {
throw new IllegalArgumentException("address must be greater than zero. Was " + getLogicalAddress());
Expand All @@ -97,6 +100,9 @@ protected ModbusTag(int address, Integer quantity, ModbusDataType dataType) {
throw new IllegalArgumentException("quantity must be greater than zero. Was " + this.quantity);
}
this.dataType = dataType != null ? dataType : ModbusDataType.INT;
this.unitId = Optional.ofNullable(config.get("unit-id"))
.map(Short::parseShort)
.orElse(null);
}

/**
Expand All @@ -107,6 +113,10 @@ public int getAddress() {
return address;
}

public Short getUnitId() {
return unitId;
}

/**
* Get the logical (configured) address
* @return The address which was configured and is different from what is used on the wire.
Expand Down Expand Up @@ -154,12 +164,13 @@ public boolean equals(Object o) {
return address == that.address &&
quantity == that.quantity &&
dataType == that.dataType &&
unitId == that.unitId &&
getClass() == that.getClass(); // MUST be identical
}

@Override
public int hashCode() {
return Objects.hash(this.getClass(), address, quantity, dataType);
return Objects.hash(this.getClass(), address, quantity, dataType, unitId);
}

@Override
Expand All @@ -168,6 +179,7 @@ public String toString() {
"address=" + address +
", quantity=" + quantity +
", dataType=" + dataType +
", unitId=" + unitId +
" }";
}

Expand All @@ -182,6 +194,9 @@ public void serialize(WriteBuffer writeBuffer) throws SerializationException {
dataType.getBytes(StandardCharsets.UTF_8).length * 8,
dataType, WithOption.WithEncoding(StandardCharsets.UTF_8.name()));

if (unitId != null) {
writeBuffer.writeUnsignedInt("unitId", 8, unitId);
}
writeBuffer.popContext(getClass().getSimpleName());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@

import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
import org.apache.plc4x.java.spi.tag.TagConfigParser;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ModbusTagCoil extends ModbusTag {

public static final String ADDRESS_PREFIX = "0x";
public static final Pattern ADDRESS_PATTERN = Pattern.compile("coil:" + ModbusTag.ADDRESS_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("0" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("0x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_PATTERN = Pattern.compile("coil:" + ModbusTag.ADDRESS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("0" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("0x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);

protected static final int REGISTER_MAXADDRESS = 65535;

public ModbusTagCoil(int address, Integer quantity, ModbusDataType dataType) {
super(address, quantity, dataType);
public ModbusTagCoil(int address, Integer quantity, ModbusDataType dataType, Map<String, String> config) {
super(address, quantity, dataType, config);
}

protected String getAddressStringPrefix() {
Expand Down Expand Up @@ -88,7 +90,7 @@ public static ModbusTagCoil of(String addressString) {

ModbusDataType dataType = (matcher.group("datatype") != null) ? ModbusDataType.valueOf(matcher.group("datatype")) : ModbusDataType.BOOL;

return new ModbusTagCoil(address, quantity, dataType);
return new ModbusTagCoil(address, quantity, dataType, TagConfigParser.parse(addressString));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@

import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
import org.apache.plc4x.java.spi.tag.TagConfigParser;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ModbusTagDiscreteInput extends ModbusTag {

public static final String ADDRESS_PREFIX = "1x";
public static final Pattern ADDRESS_PATTERN = Pattern.compile("discrete-input:" + ModbusTag.ADDRESS_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("1" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("1x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_PATTERN = Pattern.compile("discrete-input:" + ModbusTag.ADDRESS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("1" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("1x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);

protected static final int REGISTER_MAX_ADDRESS = 65535;

public ModbusTagDiscreteInput(int address, Integer quantity, ModbusDataType dataType) {
super(address, quantity, dataType);
public ModbusTagDiscreteInput(int address, Integer quantity, ModbusDataType dataType, Map<String, String> config) {
super(address, quantity, dataType, config);
}

protected String getAddressStringPrefix() {
Expand Down Expand Up @@ -88,6 +90,6 @@ public static ModbusTagDiscreteInput of(String addressString) {

ModbusDataType dataType = (matcher.group("datatype") != null) ? ModbusDataType.valueOf(matcher.group("datatype")) : ModbusDataType.BOOL;

return new ModbusTagDiscreteInput(address, quantity, dataType);
return new ModbusTagDiscreteInput(address, quantity, dataType, TagConfigParser.parse(addressString));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@

import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
import org.apache.plc4x.java.spi.tag.TagConfigParser;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ModbusTagExtendedRegister extends ModbusTag {

public static final String ADDRESS_PREFIX = "6x";
public static final Pattern ADDRESS_PATTERN = Pattern.compile("extended-register:" + ModbusTag.ADDRESS_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("6" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("6x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_PATTERN = Pattern.compile("extended-register:" + ModbusTag.ADDRESS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("6" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("6x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);

protected static final int REGISTER_MAXADDRESS = 655359999;

protected ModbusTagExtendedRegister(int address, Integer quantity, ModbusDataType dataType) {
super(address, quantity, dataType);
protected ModbusTagExtendedRegister(int address, Integer quantity, ModbusDataType dataType, Map<String, String> config) {
super(address, quantity, dataType, config);
}

protected String getAddressStringPrefix() {
Expand Down Expand Up @@ -89,6 +91,6 @@ public static ModbusTagExtendedRegister of(String addressString) {

ModbusDataType dataType = (matcher.group("datatype") != null) ? ModbusDataType.valueOf(matcher.group("datatype")) : ModbusDataType.INT;

return new ModbusTagExtendedRegister(address, quantity, dataType);
return new ModbusTagExtendedRegister(address, quantity, dataType, TagConfigParser.parse(addressString));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@

import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
import org.apache.plc4x.java.modbus.readwrite.ModbusDataType;
import org.apache.plc4x.java.spi.tag.TagConfigParser;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ModbusTagHoldingRegister extends ModbusTag {

public static final String ADDRESS_PREFIX = "4x";
public static final Pattern ADDRESS_PATTERN = Pattern.compile("holding-register:" + ModbusTag.ADDRESS_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("4" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("4x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN);
public static final Pattern ADDRESS_PATTERN = Pattern.compile("holding-register:" + ModbusTag.ADDRESS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORTER_PATTERN = Pattern.compile("4" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);
public static final Pattern ADDRESS_SHORT_PATTERN = Pattern.compile("4x" + ModbusTag.FIXED_DIGIT_MODBUS_PATTERN + TagConfigParser.TAG_CONFIG_PATTERN);

protected static final int REGISTER_MAXADDRESS = 65535;

protected ModbusTagHoldingRegister(int address, Integer quantity, ModbusDataType dataType) {
super(address, quantity, dataType);
protected ModbusTagHoldingRegister(int address, Integer quantity, ModbusDataType dataType, Map<String, String> config) {
super(address, quantity, dataType, config);
}

protected String getAddressStringPrefix() {
Expand Down Expand Up @@ -87,7 +89,7 @@ public static ModbusTagHoldingRegister of(String addressString) {

ModbusDataType dataType = (matcher.group("datatype") != null) ? ModbusDataType.valueOf(matcher.group("datatype")) : ModbusDataType.INT;

return new ModbusTagHoldingRegister(address, quantity, dataType);
return new ModbusTagHoldingRegister(address, quantity, dataType, TagConfigParser.parse(addressString));
}

}
Loading
Loading