You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2024/02/14 09:48:02 UTC
(plc4x) branch develop updated: feat: add support for nested configuration in the metadata reporting
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new 387c44f01c feat: add support for nested configuration in the metadata reporting
387c44f01c is described below
commit 387c44f01ceb94939405b381beb5c7e0c7fd9fbe
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Feb 14 10:47:49 2024 +0100
feat: add support for nested configuration in the metadata reporting
---
plc4j/drivers/all/src/site/generated/firmata.adoc | 2 +-
.../all/src/site/generated/modbus-ascii.adoc | 2 +-
.../drivers/all/src/site/generated/modbus-rtu.adoc | 2 +-
plc4j/drivers/all/src/site/generated/opcua.adoc | 5 +-
.../java/spi/connection/GeneratedDriverBase.java | 302 ++++++++-------------
5 files changed, 122 insertions(+), 191 deletions(-)
diff --git a/plc4j/drivers/all/src/site/generated/firmata.adoc b/plc4j/drivers/all/src/site/generated/firmata.adoc
index f08198567b..e6ee1a3fdd 100644
--- a/plc4j/drivers/all/src/site/generated/firmata.adoc
+++ b/plc4j/drivers/all/src/site/generated/firmata.adoc
@@ -57,7 +57,7 @@ Typical values are:
- 1
- 2
(The theoretical 1.5 stop-bits setting is not supported)
-|`serial.parity` |STRUCT |NO_PARITY| |Number of bits used to calculate data parity.
+|`serial.parity` |STRING |NO_PARITY| |Number of bits used to calculate data parity.
This is used to detect errors in transmission.
Allowed values are:
- NO_PARITY
diff --git a/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc b/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
index 203d421145..ca81e9a4ff 100644
--- a/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
+++ b/plc4j/drivers/all/src/site/generated/modbus-ascii.adoc
@@ -64,7 +64,7 @@ Typical values are:
- 1
- 2
(The theoretical 1.5 stop-bits setting is not supported)
-|`serial.parity` |STRUCT |NO_PARITY| |Number of bits used to calculate data parity.
+|`serial.parity` |STRING |NO_PARITY| |Number of bits used to calculate data parity.
This is used to detect errors in transmission.
Allowed values are:
- NO_PARITY
diff --git a/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc b/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
index 8dc898c0de..aa5648ad0a 100644
--- a/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
+++ b/plc4j/drivers/all/src/site/generated/modbus-rtu.adoc
@@ -64,7 +64,7 @@ Typical values are:
- 1
- 2
(The theoretical 1.5 stop-bits setting is not supported)
-|`serial.parity` |STRUCT |NO_PARITY| |Number of bits used to calculate data parity.
+|`serial.parity` |STRING |NO_PARITY| |Number of bits used to calculate data parity.
This is used to detect errors in transmission.
Allowed values are:
- NO_PARITY
diff --git a/plc4j/drivers/all/src/site/generated/opcua.adoc b/plc4j/drivers/all/src/site/generated/opcua.adoc
index 2bff9f83be..bbe9322694 100644
--- a/plc4j/drivers/all/src/site/generated/opcua.adoc
+++ b/plc4j/drivers/all/src/site/generated/opcua.adoc
@@ -64,7 +64,10 @@ Possible values are between others `jks`, `pkcs11`, `dks`, `jceks`.
|`session-timeout` |LONG |120000| |Expiry time for opened secure session, value in milliseconds. Defaults to 2 minutes.
|`negotiation-timeout` |LONG |60000| |Timeout for all negotiation steps prior acceptance of application level operations - this timeout applies to open secure channel, create session and close calls. Defaults to 60 seconds.
|`request-timeout` |LONG |30000| |Timeout for read/write/subscribe calls. Value in milliseconds.
-|`encoding` |STRUCT | | |TCP encoding options
+|`encoding.receive-buffer-size` |INT |Optional[65535]| |Maximum size of received TCP transport message chunk value in bytes.
+|`encoding.send-buffer-size` |INT |Optional[65535]| |Maximum size of sent transport message chunk.
+|`encoding.max-message-size` |INT |Optional[2097152]| |Maximum size of complete message.
+|`encoding.max-chunk-count` |INT |Optional[64]| |Maximum number of chunks for both sent and received messages.
5+|Transport config options:
5+| - `tcp`
|`tcp.keep-alive` |BOOLEAN |false| |Should keep-alive packets be sent?
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
index 58c1001459..127155c13a 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.java.spi.connection;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.PlcDriver;
import org.apache.plc4x.java.api.authentication.PlcAuthentication;
+import org.apache.plc4x.java.api.configuration.PlcConfiguration;
import org.apache.plc4x.java.api.configuration.PlcConnectionConfiguration;
import org.apache.plc4x.java.api.configuration.PlcTransportConfiguration;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
@@ -86,7 +87,7 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
@Override
public List<String> getSupportedTransportCodes() {
List<String> supportedTransportCodes = GeneratedDriverBase.this.getSupportedTransportCodes();
- if(supportedTransportCodes.isEmpty() && (getDefaultTransportCode().isPresent())) {
+ if (supportedTransportCodes.isEmpty() && (getDefaultTransportCode().isPresent())) {
return Collections.singletonList(getDefaultTransportCode().get());
}
return GeneratedDriverBase.this.getSupportedTransportCodes();
@@ -98,100 +99,7 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
if (clazz == null) {
return Optional.empty();
}
- var options = getAllFields(clazz).stream().map(field -> {
- String key = null;
- var configurationParameterAnnotation = field.getAnnotation(ConfigurationParameter.class);
- if (configurationParameterAnnotation != null) {
- key = configurationParameterAnnotation.value();
- if(key.isEmpty()) {
- key = field.getName();
- }
- } else {
- var complexConfigurationParameterAnnotation = field.getAnnotation(ComplexConfigurationParameter.class);
- if (complexConfigurationParameterAnnotation != null) {
- key = complexConfigurationParameterAnnotation.prefix();
- // TODO: Add support for listing the options of a complex configuration parameter.
- }
- }
- if(key == null) {
- return null;
- }
- String description = "";
- var descriptionAnnotation = field.getAnnotation(Description.class);
- if (descriptionAnnotation != null) {
- description = descriptionAnnotation.value();
- }
- boolean required = false;
- var requiredAnnotation = field.getAnnotation(Required.class);
- if (requiredAnnotation != null) {
- required = true;
- }
- OptionType type;
- switch (field.getType().getSimpleName()) {
- case "boolean":
- case "Boolean":
- type = OptionType.BOOLEAN;
- break;
- case "float":
- case "Float":
- type = OptionType.FLOAT;
- break;
- case "double":
- case "Double":
- type = OptionType.DOUBLE;
- break;
- case "int":
- case "Integer":
- type = OptionType.INT;
- break;
- case "long":
- case "Long":
- type = OptionType.LONG;
- break;
- case "String":
- type = OptionType.STRING;
- break;
- default:
- // If there's a property-converter, use "STRING" as type.
- var parameterConverterAnnotation = field.getAnnotation(ParameterConverter.class);
- if(parameterConverterAnnotation != null) {
- type = OptionType.STRING;
- } else {
- type = OptionType.STRUCT;
- }
- break;
- }
- Object defaultValue = null;
- var booleanDefaultValueAnnotation = field.getAnnotation(BooleanDefaultValue.class);
- if (booleanDefaultValueAnnotation != null) {
- defaultValue = booleanDefaultValueAnnotation.value();
- }
- var doubleDefaultValueAnnotation = field.getAnnotation(DoubleDefaultValue.class);
- if (doubleDefaultValueAnnotation != null) {
- defaultValue = doubleDefaultValueAnnotation.value();
- }
- var floatDefaultValueAnnotation = field.getAnnotation(FloatDefaultValue.class);
- if (floatDefaultValueAnnotation != null) {
- defaultValue = floatDefaultValueAnnotation.value();
- }
- var intDefaultValueAnnotation = field.getAnnotation(IntDefaultValue.class);
- if (intDefaultValueAnnotation != null) {
- defaultValue = intDefaultValueAnnotation.value();
- }
- var longDefaultValueAnnotation = field.getAnnotation(LongDefaultValue.class);
- if (longDefaultValueAnnotation != null) {
- defaultValue = longDefaultValueAnnotation.value();
- }
- var stringDefaultValueAnnotation = field.getAnnotation(StringDefaultValue.class);
- if (stringDefaultValueAnnotation != null) {
- type = OptionType.STRING;
- defaultValue = stringDefaultValueAnnotation.value();
- }
- return new DefaultOption(key, type, description, required, defaultValue);
- })
- .filter(Objects::nonNull)
- .map(Option.class::cast)
- .collect(Collectors.toList());
+ var options = getOptions(clazz);
return Optional.of(new DefaultOptionMetadata(options));
}
@@ -202,100 +110,120 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
return Optional.empty();
}
var clazz = clazzOption.get();
- var options = getAllFields(clazz).stream().map(field -> {
- String key = null;
- var configurationParameterAnnotation = field.getAnnotation(ConfigurationParameter.class);
- if (configurationParameterAnnotation != null) {
- key = configurationParameterAnnotation.value();
- if(key.isEmpty()) {
- key = field.getName();
- }
- } else {
- var complexConfigurationParameterAnnotation = field.getAnnotation(ComplexConfigurationParameter.class);
- if (complexConfigurationParameterAnnotation != null) {
- key = complexConfigurationParameterAnnotation.prefix();
- // TODO: Add support for listing the options of a complex configuration parameter.
- }
- }
- if(key == null) {
- return null;
- }
- String description = "";
- var descriptionAnnotation = field.getAnnotation(Description.class);
- if (descriptionAnnotation != null) {
- description = descriptionAnnotation.value();
- }
- boolean required = false;
- var requiredAnnotation = field.getAnnotation(Required.class);
- if (requiredAnnotation != null) {
- required = true;
- }
- OptionType type;
- switch (field.getType().getSimpleName()) {
- case "boolean":
- case "Boolean":
- type = OptionType.BOOLEAN;
- break;
- case "float":
- case "Float":
- type = OptionType.FLOAT;
- break;
- case "double":
- case "Double":
- type = OptionType.DOUBLE;
- break;
- case "int":
- case "Integer":
- type = OptionType.INT;
- break;
- case "long":
- case "Long":
- type = OptionType.LONG;
- break;
- case "String":
- type = OptionType.STRING;
- break;
- default:
- // If there's a property-converter, use "STRING" as type.
- var parameterConverterAnnotation = field.getAnnotation(ParameterConverter.class);
- if(parameterConverterAnnotation != null) {
- type = OptionType.STRING;
- } else {
- type = OptionType.STRUCT;
- }
- break;
- }
- Object defaultValue = null;
- var booleanDefaultValueAnnotation = field.getAnnotation(BooleanDefaultValue.class);
- if (booleanDefaultValueAnnotation != null) {
- defaultValue = booleanDefaultValueAnnotation.value();
- }
- var doubleDefaultValueAnnotation = field.getAnnotation(DoubleDefaultValue.class);
- if (doubleDefaultValueAnnotation != null) {
- defaultValue = doubleDefaultValueAnnotation.value();
- }
- var floatDefaultValueAnnotation = field.getAnnotation(FloatDefaultValue.class);
- if (floatDefaultValueAnnotation != null) {
- defaultValue = floatDefaultValueAnnotation.value();
- }
- var intDefaultValueAnnotation = field.getAnnotation(IntDefaultValue.class);
- if (intDefaultValueAnnotation != null) {
- defaultValue = intDefaultValueAnnotation.value();
- }
- var longDefaultValueAnnotation = field.getAnnotation(LongDefaultValue.class);
- if (longDefaultValueAnnotation != null) {
- defaultValue = longDefaultValueAnnotation.value();
- }
- var stringDefaultValueAnnotation = field.getAnnotation(StringDefaultValue.class);
- if (stringDefaultValueAnnotation != null) {
- defaultValue = stringDefaultValueAnnotation.value();
- }
- return new DefaultOption(key, type, description, required, defaultValue);
- })
+ var options = getOptions(clazz);
+ return Optional.of(new DefaultOptionMetadata(options));
+ }
+
+ private List<Option> getOptions(Class<? extends PlcConfiguration> clazz) {
+ return getAllFields(clazz).stream()
+ .map(this::optionsForField)
+ .flatMap(Collection::stream)
.filter(Objects::nonNull)
.map(Option.class::cast)
.collect(Collectors.toList());
- return Optional.of(new DefaultOptionMetadata(options));
+ }
+
+ private List<DefaultOption> optionsForField(Field field) {
+ // check if this is a complex configuration parameter and bail early
+ var complexConfigurationParameterAnnotation = field.getAnnotation(ComplexConfigurationParameter.class);
+ if (complexConfigurationParameterAnnotation != null) {
+ var prefix = complexConfigurationParameterAnnotation.prefix();
+ if (PlcConfiguration.class.isAssignableFrom(field.getType())) {
+ return getOptions((Class<? extends PlcConfiguration>) field.getType())
+ .stream()
+ .map(option -> new DefaultOption(
+ prefix + "." + option.getKey(),
+ option.getType(),
+ option.getDescription(),
+ option.isRequired(),
+ option.getDefaultValue()
+ ))
+ .collect(Collectors.toList());
+ }
+ }
+ String key = null;
+ var configurationParameterAnnotation = field.getAnnotation(ConfigurationParameter.class);
+ if (configurationParameterAnnotation != null) {
+ key = configurationParameterAnnotation.value();
+ if (key.isEmpty()) {
+ key = field.getName();
+ }
+ }
+ if (key == null) {
+ return Collections.emptyList();
+ }
+ String description = "";
+ var descriptionAnnotation = field.getAnnotation(Description.class);
+ if (descriptionAnnotation != null) {
+ description = descriptionAnnotation.value();
+ }
+ boolean required = false;
+ var requiredAnnotation = field.getAnnotation(Required.class);
+ if (requiredAnnotation != null) {
+ required = true;
+ }
+ OptionType type;
+ switch (field.getType().getSimpleName()) {
+ case "boolean":
+ case "Boolean":
+ type = OptionType.BOOLEAN;
+ break;
+ case "float":
+ case "Float":
+ type = OptionType.FLOAT;
+ break;
+ case "double":
+ case "Double":
+ type = OptionType.DOUBLE;
+ break;
+ case "int":
+ case "Integer":
+ type = OptionType.INT;
+ break;
+ case "long":
+ case "Long":
+ type = OptionType.LONG;
+ break;
+ case "String":
+ type = OptionType.STRING;
+ break;
+ default:
+ // If there's a property-converter, use "STRING" as type.
+ var parameterConverterAnnotation = field.getAnnotation(ParameterConverter.class);
+ if (parameterConverterAnnotation != null) {
+ type = OptionType.STRING;
+ } else {
+ type = OptionType.STRUCT;
+ }
+ break;
+ }
+ Object defaultValue = null;
+ var booleanDefaultValueAnnotation = field.getAnnotation(BooleanDefaultValue.class);
+ if (booleanDefaultValueAnnotation != null) {
+ defaultValue = booleanDefaultValueAnnotation.value();
+ }
+ var doubleDefaultValueAnnotation = field.getAnnotation(DoubleDefaultValue.class);
+ if (doubleDefaultValueAnnotation != null) {
+ defaultValue = doubleDefaultValueAnnotation.value();
+ }
+ var floatDefaultValueAnnotation = field.getAnnotation(FloatDefaultValue.class);
+ if (floatDefaultValueAnnotation != null) {
+ defaultValue = floatDefaultValueAnnotation.value();
+ }
+ var intDefaultValueAnnotation = field.getAnnotation(IntDefaultValue.class);
+ if (intDefaultValueAnnotation != null) {
+ defaultValue = intDefaultValueAnnotation.value();
+ }
+ var longDefaultValueAnnotation = field.getAnnotation(LongDefaultValue.class);
+ if (longDefaultValueAnnotation != null) {
+ defaultValue = longDefaultValueAnnotation.value();
+ }
+ var stringDefaultValueAnnotation = field.getAnnotation(StringDefaultValue.class);
+ if (stringDefaultValueAnnotation != null) {
+ type = OptionType.STRING;
+ defaultValue = stringDefaultValueAnnotation.value();
+ }
+ return Collections.singletonList(new DefaultOption(key, type, description, required, defaultValue));
}
@Override
@@ -497,7 +425,7 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
protected List<Field> getAllFields(Class<?> type) {
List<Field> fields = new ArrayList<>(Arrays.asList(type.getDeclaredFields()));
- if(type.getSuperclass() != null) {
+ if (type.getSuperclass() != null) {
fields.addAll(getAllFields(type.getSuperclass()));
}
return fields;