diff --git a/code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh b/code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh
index 66ec2bc4593..f81bde74061 100644
--- a/code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh
+++ b/code-generation/language-go/src/main/resources/templates/go/complex-type-template.go.ftlh
@@ -199,7 +199,10 @@ type _${type.name} struct {
${type.parentType.orElseThrow().name}Contract
#if>
<#if type.isDiscriminatedParentTypeDefinition()>
- _SubType ${type.name}
+ _SubType interface {
+ ${type.name}Contract
+ ${type.name}Requirements
+ }
#if>
<#-- Property fields are fields that require a property in the pojo -->
<#if type.propertyFields?has_content>
diff --git a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
index bd2370721bd..c842e5ebe95 100644
--- a/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
+++ b/code-generation/language-python/src/main/java/org/apache/plc4x/language/python/PythonLanguageTemplateHelper.java
@@ -579,7 +579,7 @@ public String getPlcValueTypeForTypeReference(TypeReference typeReference) {
case BYTE:
// Byte values are represented as signed integers in PLC4Py
emitRequiredImport("from plc4py.spi.values.PlcValues import PlcSINT");
- return "PlcSINT";
+ return "PlcBYTE";
case UINT:
IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
if (unsignedIntegerTypeReference.getSizeInBits() <= 4) {
@@ -807,10 +807,10 @@ public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReferenc
switch (simpleTypeReference.getBaseType()) {
case BIT:
String bitType = "bit";
- return "read_buffer.read_" + bitType + "(\"" + logicalName + "\")";
+ return "read_buffer.read_" + bitType + "(\"" + logicalName + "\"";
case BYTE:
String byteType = "byte";
- return "read_buffer.read_" + byteType + "(\"" + logicalName + "\")";
+ return "read_buffer.read_" + byteType + "(\"" + logicalName + "\"";
case UINT:
String unsignedIntegerType;
IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
@@ -825,7 +825,7 @@ public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReferenc
} else {
unsignedIntegerType = "unsigned_long";
}
- return "read_buffer.read_" + unsignedIntegerType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\")";
+ return "read_buffer.read_" + unsignedIntegerType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\"";
case INT:
String integerType;
if (simpleTypeReference.getSizeInBits() <= 8) {
@@ -839,10 +839,10 @@ public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReferenc
} else {
integerType = "long";
}
- return "read_buffer.read_" + integerType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\")";
+ return "read_buffer.read_" + integerType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\"";
case FLOAT:
String floatType = (simpleTypeReference.getSizeInBits() <= 32) ? "float" : "double";
- return "read_buffer.read_" + floatType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\")";
+ return "read_buffer.read_" + floatType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\"";
case STRING:
case VSTRING:
String stringType = "str";
@@ -856,7 +856,7 @@ public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReferenc
VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
length = toParseExpression(field, INT_TYPE_REFERENCE, vstringTypeReference.getLengthExpression(), null);
}
- return "read_buffer.read_" + stringType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\", encoding=" + "\"\")";
+ return "read_buffer.read_" + stringType + "(" + simpleTypeReference.getSizeInBits() + ", logical_name=\"" + logicalName + "\"";
default:
return "";
@@ -895,7 +895,8 @@ public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeRefere
case BIT:
return "write_buffer.write_bit(" + fieldName + ", \"" + logicalName + "\"" + writerArgsString + ")";
case BYTE:
- return "write_buffer.write_byte(" + fieldName + ", \"" + logicalName + "\"" + writerArgsString + ")";
+ ByteTypeReference byteTypeReference = (ByteTypeReference) simpleTypeReference;
+ return "write_buffer.write_byte(" + fieldName + ", " + byteTypeReference.getSizeInBits() + ", \"" + logicalName + "\"" + writerArgsString + ")";
case UINT:
IntegerTypeReference unsignedIntegerTypeReference = (IntegerTypeReference) simpleTypeReference;
if (unsignedIntegerTypeReference.getSizeInBits() <= 8) {
@@ -945,7 +946,7 @@ public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeRefere
.orElseThrow(() -> new FreemarkerException("Encoding must be a quoted string value")).getValue();
String length = Integer.toString(simpleTypeReference.getSizeInBits());
return "write_buffer.write_str(" + fieldName + ", " + length + ", \"" +
- encoding + "\", \"" + logicalName + "\"" + writerArgsString + ")";
+ logicalName + "\", \"" + encoding + "\"" + writerArgsString + ")";
}
case VSTRING: {
VstringTypeReference vstringTypeReference = (VstringTypeReference) simpleTypeReference;
@@ -957,7 +958,7 @@ public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeRefere
String lengthExpression = toExpression(field, null, vstringTypeReference.getLengthExpression(), null, Collections.singletonList(new DefaultArgument("stringLength", new DefaultIntegerTypeReference(SimpleTypeReference.SimpleBaseType.INT, 32))), true, false);
String length = Integer.toString(simpleTypeReference.getSizeInBits());
return "write_buffer.write_str(" + fieldName + ", " + lengthExpression + ", \"" +
- encoding + "\", \"" + logicalName + "\"" + writerArgsString + ")";
+ logicalName + "\", \"" + encoding + "\"" + writerArgsString + ")";
}
case DATE:
case TIME:
@@ -1511,7 +1512,7 @@ else if ((variableLiteral.getChild().isPresent()) && ((ComplexTypeDefinition) th
} else if ((serializerArguments != null) && serializerArguments.stream()
.anyMatch(argument -> argument.getName().equals(variableLiteralName))) {
tracer = tracer.dive("serialization argument");
- return tracer + "self." + camelCaseToSnakeCase(variableLiteralName) +
+ return tracer + camelCaseToSnakeCase(variableLiteralName) +
variableLiteral.getChild()
.map(child -> "." + camelCaseToSnakeCase(toVariableExpression(field, typeReference, child, parserArguments, serializerArguments, serialize, suppressPointerAccess, true)))
.orElse("");
diff --git a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
index 626d950a536..10a98c6a29c 100644
--- a/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
+++ b/code-generation/language-python/src/main/resources/templates/python/complex-type-template.python.ftlh
@@ -565,7 +565,7 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()>#if>(<#if ty
<#if parserArgument.type.isEnumTypeReference()>
${helper.camelCaseToSnakeCase(parserArgument.name)} = ${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)}[${helper.camelCaseToSnakeCase(parserArgument.name)}]
<#elseif helper.getLanguageTypeNameForTypeReference(parserArgument.type, false) = "bool">
- <@emitImport import="from distutils.util import strtobool" />
+ <@emitImport import="from plc4py.utils.ConnectionStringHandling import strtobool" />
${helper.camelCaseToSnakeCase(parserArgument.name)} = bool(strtobool(${helper.camelCaseToSnakeCase(parserArgument.name)}))
<#else>
${helper.camelCaseToSnakeCase(parserArgument.name)} = ${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)}(${helper.camelCaseToSnakeCase(parserArgument.name)})
diff --git a/code-generation/language-python/src/main/resources/templates/python/data-io-template.python.ftlh b/code-generation/language-python/src/main/resources/templates/python/data-io-template.python.ftlh
index 029c4854085..839fa2477ea 100644
--- a/code-generation/language-python/src/main/resources/templates/python/data-io-template.python.ftlh
+++ b/code-generation/language-python/src/main/resources/templates/python/data-io-template.python.ftlh
@@ -89,6 +89,7 @@ class ${type.name}:
<#switch field.typeName>
<#case "array">
<#assign arrayField = field.asArrayField().orElseThrow()>
+ <#assign typedField = field.asTypedField().orElseThrow()>
<#assign elementTypeReference=arrayField.type.elementTypeReference>
# Array field (${helper.camelCaseToSnakeCase(arrayField.name)})
<#-- Only update curPos if the length expression uses it -->
@@ -103,7 +104,7 @@ class ${type.name}:
<@emitImport import="from plc4py.api.value.PlcValue import PlcValue" />
${helper.camelCaseToSnakeCase(arrayField.name)}: List[PlcValue] = []
for _ in range(item_count):
- ${helper.camelCaseToSnakeCase(arrayField.name)}.append(${helper.getPlcValueTypeForTypeReference(elementTypeReference)}(${helper.getLanguageTypeNameForTypeReference(elementTypeReference, false)}(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)})<#else>${elementTypeReference.asComplexTypeReference().orElseThrow().name}IO.static_parse(read_buffer<#if elementTypeReference.params.isPresent()>, <#list elementTypeReference.params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, elementTypeReference, parserArgument,parserArguments)})<#sep>, #sep>#list>#if>)#if>))
+ ${helper.camelCaseToSnakeCase(arrayField.name)}.append(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)}${helper.getFieldOptions(typedField, parserArguments)}))<#else>${elementTypeReference.asComplexTypeReference().orElseThrow().name}IO.static_parse(read_buffer<#if elementTypeReference.params.isPresent()>, <#list elementTypeReference.params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, elementTypeReference, parserArgument,parserArguments)})<#sep>, #sep>#list>#if>)#if>
<#-- In all other cases do we have to work with a list, that is later converted to an array -->
<#else>
@@ -118,7 +119,7 @@ class ${type.name}:
while read_buffer.get_pos() < ${helper.camelCaseToSnakeCase(arrayField.name)}_end_pos):
value.append(<@compress single_line=true>
<#if elementTypeReference.isSimpleTypeReference()>
- ${helper.getPlcValueTypeForTypeReference(elementTypeReference)}(${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)})
+ ${helper.getPlcValueTypeForTypeReference(elementTypeReference)}(${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)}${helper.getFieldOptions(typedField, parserArguments)}))
<#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.static_parse(readBuffer
<#if elementTypeReference.params.isPresent()>,
<#list elementTypeReference.params.orElseThrow() as parserArgument>
@@ -136,7 +137,7 @@ class ${type.name}:
# Terminated array
${arrayField.name}: ${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)} = new LinkedList<>()
while not bool(${helper.camelCaseToSnakeCase(helper.toParseExpression(arrayField, helper.boolTypeReference, arrayField.loopExpression,parserArguments))})):
- ${helper.camelCaseToSnakeCase(arrayField.name)}.append(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)}<#else>${elementTypeReference.asComplexTypeReference().orElseThrow().name}IO.static_parse(readBuffer<#if arrayField.params.isPresent()>, <#list arrayField.params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parserArgument,parserArguments)})<#sep>, #sep>#list>#if>)#if>)
+ ${helper.camelCaseToSnakeCase(arrayField.name)}.append(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)}${helper.getFieldOptions(typedField, parserArguments)})<#else>${elementTypeReference.asComplexTypeReference().orElseThrow().name}IO.static_parse(readBuffer<#if arrayField.params.isPresent()>, <#list arrayField.params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parserArgument,parserArguments)})<#sep>, #sep>#list>#if>)#if>)
<#-- After parsing, update the current position, but only if it's needed -->
<#if arrayField.loopExpression.contains("curPos")>
@@ -151,9 +152,10 @@ class ${type.name}:
<#break>
<#case "const">
<#assign constField=field.asConstField().orElseThrow()>
+ <#assign typedField = field.asTypedField().orElseThrow()>
# Const Field (${helper.camelCaseToSnakeCase(constField.name)})
- ${helper.camelCaseToSnakeCase(constField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(constField)} = ${helper.getReadBufferReadMethodCall(constField.type.asSimpleTypeReference().orElseThrow(), "", constField)}
+ ${helper.camelCaseToSnakeCase(constField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(constField)} = ${helper.getReadBufferReadMethodCall(constField.type.asSimpleTypeReference().orElseThrow(), "", constField)}${helper.getFieldOptions(typedField, parserArguments)})
if ${helper.camelCaseToSnakeCase(constField.name)} != ${dataIoTypeDefinition.name}.${constField.name?upper_case}):
<@emitImport import="from plc4py.api.exceptions.exceptions import ParseException" />
raise ParseException("Expected constant value " + ${dataIoTypeDefinition.name}.${constField.name?upper_case} + " but got " + ${helper.camelCaseToSnakeCase(constField.name)})
@@ -164,9 +166,10 @@ class ${type.name}:
<#break>
<#case "enum">
<#assign enumField=field.asEnumField().orElseThrow()>
+ <#assign typedField = field.asTypedField().orElseThrow()>
# Enum field (${helper.camelCaseToSnakeCase(enumField.name)})
- ${helper.camelCaseToSnakeCase(enumField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(enumField)} = ${helper.getNonPrimitiveLanguageTypeNameForField(enumField)}.enum_for_value(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type.asSimpleTypeReference().orElseThrow()), "", enumField)})
+ ${helper.camelCaseToSnakeCase(enumField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(enumField)} = ${helper.getNonPrimitiveLanguageTypeNameForField(enumField)}.enum_for_value(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type.asSimpleTypeReference().orElseThrow()), "", enumField)}${helper.getFieldOptions(typedField, parserArguments)}))
<#if enumField.name == "value">
<#assign valueDefined=true>
#if>
@@ -182,22 +185,24 @@ class ${type.name}:
<#break>
<#case "reserved">
<#assign reservedField=field.asReservedField().orElseThrow()>
+ <#assign typedField = field.asTypedField().orElseThrow()>
# Reserved Field (Compartmentalized so the "reserved" variable can't leak)
- reserved: ${helper.getLanguageTypeNameForField(field)} = ${helper.getReadBufferReadMethodCall(reservedField.type.asSimpleTypeReference().orElseThrow(), "", reservedField)}
+ reserved: ${helper.getLanguageTypeNameForField(field)} = ${helper.getReadBufferReadMethodCall(reservedField.type.asSimpleTypeReference().orElseThrow(), "", reservedField)}${helper.getFieldOptions(typedField, parserArguments)})
if reserved != ${helper.getReservedValue(reservedField)}:
<@emitImport import="import logging" />
logging.warning("Expected constant value " + str(${reservedField.referenceValue}) + " but got " + str(reserved) + " for reserved field.")
<#break>
<#case "simple">
<#assign simpleField=field.asSimpleField().orElseThrow()>
+ <#assign typedField = field.asTypedField().orElseThrow()>
<#if helper.isEnumField(simpleField)>
# Enum field (${simpleField.name})
- ${helper.camelCaseToSnakeCase(simpleField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(simpleField)} = ${helper.getNonPrimitiveLanguageTypeNameForField(simpleField)}(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)})
+ ${helper.camelCaseToSnakeCase(simpleField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(simpleField)} = ${helper.getNonPrimitiveLanguageTypeNameForField(simpleField)}(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)}${helper.getFieldOptions(typedField, parserArguments)}))
<#else>
# Simple Field (${simpleField.name})
- ${helper.camelCaseToSnakeCase(simpleField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(simpleField)} = <#if simpleField.type.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(simpleField.type.asSimpleTypeReference().orElseThrow(), "", simpleField)}<#else>${simpleField.type.asComplexTypeReference().orElseThrow().name}IO.staticParse(readBuffer<#if simpleField.params.isPresent()>, <#list field.params.orElseThrow() as parserArgument>${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index), true)}(${helper.toParseExpression(simpleField, simpleField.type, parserArgument,parserArguments)})<#sep>, #sep>#list>#if>)#if>
+ ${helper.camelCaseToSnakeCase(simpleField.name)}: ${helper.getNonPrimitiveLanguageTypeNameForField(simpleField)} = <#if simpleField.type.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(simpleField.type.asSimpleTypeReference().orElseThrow(), "", simpleField)}${helper.getFieldOptions(typedField, parserArguments)})<#else>${simpleField.type.asComplexTypeReference().orElseThrow().name}IO.staticParse(readBuffer<#if simpleField.params.isPresent()>, <#list field.params.orElseThrow() as parserArgument>${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(simpleField.type, parserArgument?index), true)}(${helper.toParseExpression(simpleField, simpleField.type, parserArgument,parserArguments)})<#sep>, #sep>#list>#if>${helper.getFieldOptions(typedField, parserArguments)})#if>
#if>
<#if case.name == "Struct" ||
((case.name == "DATE_AND_TIME") && ((simpleField.name == "year") || (simpleField.name == "month") || (simpleField.name == "day") || (simpleField.name == "hour") || (simpleField.name == "minutes") || (simpleField.name == "seconds"))) ||
@@ -289,7 +294,8 @@ class ${type.name}:
<#break>
<#case "DATE">
<#if helper.hasFieldsWithNames(case.fields, "year", "month", "day")>
- value: LocalDate = LocalDate(int(year), (month == 0) ? 1 : int(month), (day == 0) ? 1 : int(day))
+ <@emitImport import="import datetime" />
+ value: datetime = datetime.datetime(int(year), int(month), int(day))
#if>
<@emitImport import="from plc4py.spi.values.PlcValues import PlcDATE" />
return PlcDATE(value)
@@ -304,12 +310,10 @@ class ${type.name}:
return PlcTIME_OF_DAY(value)
<#break>
<#case "DATE_AND_TIME">
- <#if helper.hasFieldsWithNames(case.fields, "year", "month", "day", "hour", "minutes", "seconds", "nanos")>
- value: LocalDateTime = LocalDateTime(int(year), (month == 0) ? 1 : int(month), (day == 0) ? 1 : int(day), int(hour), int(minutes), int(seconds), int(nanos))
+ <#if helper.hasFieldsWithNames(case.fields, "year", "month", "day", "hour", "minutes", "seconds", "microseconds")>
+ value: datetime = datetime.datetime(int(year), int(month), int(day), int(hour), int(minutes), int(seconds), int(microseconds))
<#elseif helper.hasFieldsWithNames(case.fields, "year", "month", "day", "hour", "minutes", "seconds")>
- value: LocalDateTime = LocalDateTime(int(year), (month == 0) ? 1 : int(month), (day == 0) ? 1 : int(day), int(hour), int(minutes), int(seconds))
- <#elseif helper.hasFieldsWithNames(case.fields, "secondsSinceEpoch")>
- value: LocalDateTime = LocalDateTime.ofEpochSecond(secondsSinceEpoch, 0, ZoneOffset.UTC)
+ value: datetime = datetime.datetime(int(year), int(month), int(day), int(hour), int(minutes), int(seconds))
#if>
<@emitImport import="from plc4py.spi.values.PlcValues import PlcDATE_AND_TIME" />
return PlcDATE_AND_TIME(value)
@@ -368,7 +372,7 @@ class ${type.name}:
for val in values.getStruct().get("${arrayField.name}").get_list():
<#if elementTypeReference.isByteBased()>
value: ${helper.getLanguageTypeNameForField(arrayField)} = val.get_raw()
- write_buffer.write_byte_array("", value)
+ write_buffer.write_byte(value, 8, "")
<#else>
value: ${helper.getLanguageTypeNameForField(arrayField)} = val.get_${helper.camelCaseToSnakeCase(helper.getLanguageTypeNameForField(arrayField)?cap_first)}()
${helper.getWriteBufferWriteMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "value", arrayField)}
@@ -378,7 +382,7 @@ class ${type.name}:
<#if elementTypeReference.isByteBased()>
<@emitImport import="from typing import List" />
value: ${helper.getLanguageTypeNameForField(arrayField)} = val.get_raw()
- write_buffer.write_byte_array("", value)
+ write_buffer.write_byte(value, 8, "")
<#else>
value: ${helper.getLanguageTypeNameForTypeReference(elementTypeReference)} = val.get_${helper.camelCaseToSnakeCase(helper.getLanguageTypeNameForTypeReference(elementTypeReference)?cap_first)}()
${helper.getWriteBufferWriteMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "(" + arrayField.name + ")", arrayField)}
@@ -406,7 +410,9 @@ class ${type.name}:
<#case "manual">
<#assign manualField=field.asManualField().orElseThrow()>
# Manual Field (${manualField.name})
- ${helper.toSerializationExpression(manualField, manualField.type, manualField.serializeExpression, type.parserArguments.orElse(null))}
+ <@emitImport import="from plc4py.protocols.${protocolName} import StaticHelper" />
+ value: PlcValue = _value
+ StaticHelper.${helper.toSerializationExpression(manualField, manualField.type, manualField.serializeExpression, type.parserArguments.orElse(null))}
<#break>
<#case "reserved">
diff --git a/code-generation/language-python/src/test/resources/plc4py/pom.xml b/code-generation/language-python/src/test/resources/plc4py/pom.xml
index 059fea2df21..f9b131f540b 100644
--- a/code-generation/language-python/src/test/resources/plc4py/pom.xml
+++ b/code-generation/language-python/src/test/resources/plc4py/pom.xml
@@ -53,7 +53,7 @@
.${project.basedir}/../../../../../plc4py/
- setup.*
+ pyproject.tomltrue
@@ -219,35 +219,36 @@
- python-black
+ python-test-compileprocess-sourcesexec
- ${python.venv.bin}${python.exe.bin}
+ ${python.venv.bin}pip3
- -m
- black
- .
+ install
+ .[dev]
- python-test-compile
- test-compile
+ python-black
+ process-sourcesexec
- ${python.venv.bin}pip3
+ ${python.venv.bin}${python.exe.bin}
- install
- .[dev]
+ -m
+ black
+ .
+
diff --git a/plc4go/assets/testing/protocols/opcua/ParserSerializerTestsuite.xml b/plc4go/assets/testing/protocols/opcua/ParserSerializerTestsuite.xml
index 9fc863cfd5b..488655b5b0b 100644
--- a/plc4go/assets/testing/protocols/opcua/ParserSerializerTestsuite.xml
+++ b/plc4go/assets/testing/protocols/opcua/ParserSerializerTestsuite.xml
@@ -1,24 +1,24 @@
+ byteOrder="LITTLE_ENDIAN">
OPCUA
@@ -65,7 +65,7 @@
OPC UA Anonymous Identity Token09000000616e6f6e796d6f7573
- UserIdentityToken
+ ExtensionObjectDefinition321
@@ -142,7 +142,7 @@
OPC UA Activate Session request0500002000000084428062123302a3e7470f91899aa477deeab6ba1d83368c8a8e1a5bfffefa6de065de8f04edda010200000000000000ffffffff30750000000000ffffffffffffffff000000000000000001004101010d00000009000000616e6f6e796d6f7573ffffffffffffffff
- ActivateSessionRequest
+ ExtensionObjectDefinition467
@@ -311,7 +311,7 @@
OPC UA Publish Response Payload (data change)20427b9004edda01350000000000000000ffffffff000000010000000100000001000000000100000020427b9004edda010100000001002b03012200000001000000010000000d0620000000f0cc098e04edda017089e98f04edda01000000000000000000000000
- PublishResponse
+ ExtensionObjectDefinition829
@@ -484,7 +484,7 @@
OPC UA Publish Response Payload (event notification)a07f7459ddf3da016c0200000000000000ffffffff0000000300000001000000010000000001000000a07f7459ddf3da010100000001009403012301000003000000050000000b0000000000000f08000000000000000000001a0c06000000536572766572050100110100cd081503000000000d000000526566726573682053746172740d5040e158ddf3da01110100e30a110000050000000b00000001000100000f10000000000000000000001700000000000000120c070000004d794c6576656c05f40111030600070000004d794c6576656c1503000000000e0000004c6576656c2065786365656465640d20110558ddf3da011101000a25110306000d0000004d794c6576656c2e416c61726d050000000b0000000000000f08000000000000000000001b0c06000000536572766572050100110100cd081503000000000b0000005265667265736820456e640d6067e158ddf3da01110100e40a1100000100000000002880ffffffff
- PublishResponse
+ ExtensionObjectDefinition829
@@ -1244,7 +1244,7 @@
OPC UA Notification Message010000008084ff018fedda010100000001002b03012200000001000000010000000d062000000000222ffb8eedda0120d592008fedda0100000000
- PublishResponse
+ ExtensionObjectDefinition805
@@ -1427,7 +1427,7 @@
OPC UA Monitored Item Notification010000000d062000000000222ffb8eedda0120d592008fedda01
- MonitoredItemNotification
+ ExtensionObjectDefinition808
diff --git a/plc4go/go.mod b/plc4go/go.mod
index 45435616cd5..5f69706f775 100644
--- a/plc4go/go.mod
+++ b/plc4go/go.mod
@@ -25,7 +25,7 @@ require (
github.com/IBM/netaddr v1.5.0
github.com/ajankovic/xdiff v0.0.1
github.com/cstockton/go-conv v1.0.0
- github.com/fatih/color v1.17.0
+ github.com/fatih/color v1.18.0
github.com/google/uuid v1.6.0
github.com/gopacket/gopacket v1.3.0
github.com/icza/bitio v1.1.0
diff --git a/plc4go/go.sum b/plc4go/go.sum
index bc5978f5d26..da770e69b49 100644
--- a/plc4go/go.sum
+++ b/plc4go/go.sum
@@ -11,8 +11,8 @@ github.com/cstockton/go-conv v1.0.0/go.mod h1:HuiHkkRgOA0IoBNPC7ysG7kNpjDYlgM7Kj
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
-github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
+github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
+github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
diff --git a/plc4go/protocols/abeth/readwrite/model/CIPEncapsulationPacket.go b/plc4go/protocols/abeth/readwrite/model/CIPEncapsulationPacket.go
index a7c3a3361be..cd827ed3950 100644
--- a/plc4go/protocols/abeth/readwrite/model/CIPEncapsulationPacket.go
+++ b/plc4go/protocols/abeth/readwrite/model/CIPEncapsulationPacket.go
@@ -75,7 +75,10 @@ type CIPEncapsulationPacketRequirements interface {
// _CIPEncapsulationPacket is the data-structure of this message
type _CIPEncapsulationPacket struct {
- _SubType CIPEncapsulationPacket
+ _SubType interface {
+ CIPEncapsulationPacketContract
+ CIPEncapsulationPacketRequirements
+ }
SessionHandle uint32
Status uint32
SenderContext []uint8
diff --git a/plc4go/protocols/abeth/readwrite/model/DF1RequestCommand.go b/plc4go/protocols/abeth/readwrite/model/DF1RequestCommand.go
index 853a12d318e..a5a59645724 100644
--- a/plc4go/protocols/abeth/readwrite/model/DF1RequestCommand.go
+++ b/plc4go/protocols/abeth/readwrite/model/DF1RequestCommand.go
@@ -65,7 +65,10 @@ type DF1RequestCommandRequirements interface {
// _DF1RequestCommand is the data-structure of this message
type _DF1RequestCommand struct {
- _SubType DF1RequestCommand
+ _SubType interface {
+ DF1RequestCommandContract
+ DF1RequestCommandRequirements
+ }
}
var _ DF1RequestCommandContract = (*_DF1RequestCommand)(nil)
diff --git a/plc4go/protocols/abeth/readwrite/model/DF1RequestMessage.go b/plc4go/protocols/abeth/readwrite/model/DF1RequestMessage.go
index c686b71005c..5f3c5832896 100644
--- a/plc4go/protocols/abeth/readwrite/model/DF1RequestMessage.go
+++ b/plc4go/protocols/abeth/readwrite/model/DF1RequestMessage.go
@@ -73,7 +73,10 @@ type DF1RequestMessageRequirements interface {
// _DF1RequestMessage is the data-structure of this message
type _DF1RequestMessage struct {
- _SubType DF1RequestMessage
+ _SubType interface {
+ DF1RequestMessageContract
+ DF1RequestMessageRequirements
+ }
DestinationAddress uint8
SourceAddress uint8
Status uint8
diff --git a/plc4go/protocols/abeth/readwrite/model/DF1ResponseMessage.go b/plc4go/protocols/abeth/readwrite/model/DF1ResponseMessage.go
index a31ba1c2b10..db417920650 100644
--- a/plc4go/protocols/abeth/readwrite/model/DF1ResponseMessage.go
+++ b/plc4go/protocols/abeth/readwrite/model/DF1ResponseMessage.go
@@ -75,7 +75,10 @@ type DF1ResponseMessageRequirements interface {
// _DF1ResponseMessage is the data-structure of this message
type _DF1ResponseMessage struct {
- _SubType DF1ResponseMessage
+ _SubType interface {
+ DF1ResponseMessageContract
+ DF1ResponseMessageRequirements
+ }
DestinationAddress uint8
SourceAddress uint8
Status uint8
diff --git a/plc4go/protocols/ads/discovery/readwrite/model/AdsDiscoveryBlock.go b/plc4go/protocols/ads/discovery/readwrite/model/AdsDiscoveryBlock.go
index 0f605b642ec..3ec55530f1a 100644
--- a/plc4go/protocols/ads/discovery/readwrite/model/AdsDiscoveryBlock.go
+++ b/plc4go/protocols/ads/discovery/readwrite/model/AdsDiscoveryBlock.go
@@ -65,7 +65,10 @@ type AdsDiscoveryBlockRequirements interface {
// _AdsDiscoveryBlock is the data-structure of this message
type _AdsDiscoveryBlock struct {
- _SubType AdsDiscoveryBlock
+ _SubType interface {
+ AdsDiscoveryBlockContract
+ AdsDiscoveryBlockRequirements
+ }
}
var _ AdsDiscoveryBlockContract = (*_AdsDiscoveryBlock)(nil)
diff --git a/plc4go/protocols/ads/readwrite/model/AdsMultiRequestItem.go b/plc4go/protocols/ads/readwrite/model/AdsMultiRequestItem.go
index 67bf6fc90a9..17f75f58f54 100644
--- a/plc4go/protocols/ads/readwrite/model/AdsMultiRequestItem.go
+++ b/plc4go/protocols/ads/readwrite/model/AdsMultiRequestItem.go
@@ -63,7 +63,10 @@ type AdsMultiRequestItemRequirements interface {
// _AdsMultiRequestItem is the data-structure of this message
type _AdsMultiRequestItem struct {
- _SubType AdsMultiRequestItem
+ _SubType interface {
+ AdsMultiRequestItemContract
+ AdsMultiRequestItemRequirements
+ }
}
var _ AdsMultiRequestItemContract = (*_AdsMultiRequestItem)(nil)
diff --git a/plc4go/protocols/ads/readwrite/model/AmsPacket.go b/plc4go/protocols/ads/readwrite/model/AmsPacket.go
index a155bfc984e..9d70d26d5e1 100644
--- a/plc4go/protocols/ads/readwrite/model/AmsPacket.go
+++ b/plc4go/protocols/ads/readwrite/model/AmsPacket.go
@@ -91,7 +91,10 @@ type AmsPacketRequirements interface {
// _AmsPacket is the data-structure of this message
type _AmsPacket struct {
- _SubType AmsPacket
+ _SubType interface {
+ AmsPacketContract
+ AmsPacketRequirements
+ }
TargetAmsNetId AmsNetId
TargetAmsPort uint16
SourceAmsNetId AmsNetId
diff --git a/plc4go/protocols/bacnetip/readwrite/model/APDU.go b/plc4go/protocols/bacnetip/readwrite/model/APDU.go
index b0d5638f609..7ce2c5fb182 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/APDU.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/APDU.go
@@ -67,7 +67,10 @@ type APDURequirements interface {
// _APDU is the data-structure of this message
type _APDU struct {
- _SubType APDU
+ _SubType interface {
+ APDUContract
+ APDURequirements
+ }
// Arguments.
ApduLength uint16
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetApplicationTag.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetApplicationTag.go
index 2861c24067f..d28be087fcb 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetApplicationTag.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetApplicationTag.go
@@ -71,8 +71,11 @@ type BACnetApplicationTagRequirements interface {
// _BACnetApplicationTag is the data-structure of this message
type _BACnetApplicationTag struct {
- _SubType BACnetApplicationTag
- Header BACnetTagHeader
+ _SubType interface {
+ BACnetApplicationTagContract
+ BACnetApplicationTagRequirements
+ }
+ Header BACnetTagHeader
}
var _ BACnetApplicationTagContract = (*_BACnetApplicationTag)(nil)
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetCalendarEntry.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetCalendarEntry.go
index 42b50352eac..67787aa7eb7 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetCalendarEntry.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetCalendarEntry.go
@@ -69,7 +69,10 @@ type BACnetCalendarEntryRequirements interface {
// _BACnetCalendarEntry is the data-structure of this message
type _BACnetCalendarEntry struct {
- _SubType BACnetCalendarEntry
+ _SubType interface {
+ BACnetCalendarEntryContract
+ BACnetCalendarEntryRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetChannelValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetChannelValue.go
index dad32625877..1bd82d1bde6 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetChannelValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetChannelValue.go
@@ -73,7 +73,10 @@ type BACnetChannelValueRequirements interface {
// _BACnetChannelValue is the data-structure of this message
type _BACnetChannelValue struct {
- _SubType BACnetChannelValue
+ _SubType interface {
+ BACnetChannelValueContract
+ BACnetChannelValueRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetClientCOV.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetClientCOV.go
index 4b459ed3da4..e7faf3594d0 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetClientCOV.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetClientCOV.go
@@ -69,7 +69,10 @@ type BACnetClientCOVRequirements interface {
// _BACnetClientCOV is the data-structure of this message
type _BACnetClientCOV struct {
- _SubType BACnetClientCOV
+ _SubType interface {
+ BACnetClientCOVContract
+ BACnetClientCOVRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequest.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequest.go
index 0281e07bada..82748f545a2 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequest.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequest.go
@@ -69,7 +69,10 @@ type BACnetConfirmedServiceRequestRequirements interface {
// _BACnetConfirmedServiceRequest is the data-structure of this message
type _BACnetConfirmedServiceRequest struct {
- _SubType BACnetConfirmedServiceRequest
+ _SubType interface {
+ BACnetConfirmedServiceRequestContract
+ BACnetConfirmedServiceRequestRequirements
+ }
// Arguments.
ServiceRequestLength uint32
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord.go
index b4d75216ea0..d9fd639fc4b 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord.go
@@ -73,7 +73,10 @@ type BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecordRequirements inter
// _BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord is the data-structure of this message
type _BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord struct {
- _SubType BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecord
+ _SubType interface {
+ BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecordContract
+ BACnetConfirmedServiceRequestAtomicReadFileStreamOrRecordRequirements
+ }
PeekedTagHeader BACnetTagHeader
OpeningTag BACnetOpeningTag
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass.go
index 68f96722d30..ccfe8913912 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass.go
@@ -75,7 +75,10 @@ type BACnetConfirmedServiceRequestConfirmedTextMessageMessageClassRequirements i
// _BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass is the data-structure of this message
type _BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass struct {
- _SubType BACnetConfirmedServiceRequestConfirmedTextMessageMessageClass
+ _SubType interface {
+ BACnetConfirmedServiceRequestConfirmedTextMessageMessageClassContract
+ BACnetConfirmedServiceRequestConfirmedTextMessageMessageClassRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadRangeRange.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadRangeRange.go
index cb09db49954..e61bb5c4df0 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadRangeRange.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetConfirmedServiceRequestReadRangeRange.go
@@ -73,7 +73,10 @@ type BACnetConfirmedServiceRequestReadRangeRangeRequirements interface {
// _BACnetConfirmedServiceRequestReadRangeRange is the data-structure of this message
type _BACnetConfirmedServiceRequestReadRangeRange struct {
- _SubType BACnetConfirmedServiceRequestReadRangeRange
+ _SubType interface {
+ BACnetConfirmedServiceRequestReadRangeRangeContract
+ BACnetConfirmedServiceRequestReadRangeRangeRequirements
+ }
PeekedTagHeader BACnetTagHeader
OpeningTag BACnetOpeningTag
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetConstructedData.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetConstructedData.go
index 0fdc67a4e9f..22100ee0ddb 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetConstructedData.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetConstructedData.go
@@ -81,7 +81,10 @@ type BACnetConstructedDataRequirements interface {
// _BACnetConstructedData is the data-structure of this message
type _BACnetConstructedData struct {
- _SubType BACnetConstructedData
+ _SubType interface {
+ BACnetConstructedDataContract
+ BACnetConstructedDataRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetContextTag.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetContextTag.go
index 2af4f444c63..919fbafef00 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetContextTag.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetContextTag.go
@@ -73,8 +73,11 @@ type BACnetContextTagRequirements interface {
// _BACnetContextTag is the data-structure of this message
type _BACnetContextTag struct {
- _SubType BACnetContextTag
- Header BACnetTagHeader
+ _SubType interface {
+ BACnetContextTagContract
+ BACnetContextTagRequirements
+ }
+ Header BACnetTagHeader
// Arguments.
TagNumberArgument uint8
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetError.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetError.go
index fe39213fb4c..646285eb95a 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetError.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetError.go
@@ -63,7 +63,10 @@ type BACnetErrorRequirements interface {
// _BACnetError is the data-structure of this message
type _BACnetError struct {
- _SubType BACnetError
+ _SubType interface {
+ BACnetErrorContract
+ BACnetErrorRequirements
+ }
}
var _ BACnetErrorContract = (*_BACnetError)(nil)
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetEventLogRecordLogDatum.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetEventLogRecordLogDatum.go
index f7908bd6dd5..73d6203d3ed 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetEventLogRecordLogDatum.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetEventLogRecordLogDatum.go
@@ -75,7 +75,10 @@ type BACnetEventLogRecordLogDatumRequirements interface {
// _BACnetEventLogRecordLogDatum is the data-structure of this message
type _BACnetEventLogRecordLogDatum struct {
- _SubType BACnetEventLogRecordLogDatum
+ _SubType interface {
+ BACnetEventLogRecordLogDatumContract
+ BACnetEventLogRecordLogDatumRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameter.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameter.go
index 5d34e2392de..1ebea8b5a05 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameter.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameter.go
@@ -69,7 +69,10 @@ type BACnetEventParameterRequirements interface {
// _BACnetEventParameter is the data-structure of this message
type _BACnetEventParameter struct {
- _SubType BACnetEventParameter
+ _SubType interface {
+ BACnetEventParameterContract
+ BACnetEventParameterRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameterChangeOfValueCivCriteria.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameterChangeOfValueCivCriteria.go
index c73886bc0c3..fe06295f3a8 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameterChangeOfValueCivCriteria.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetEventParameterChangeOfValueCivCriteria.go
@@ -75,7 +75,10 @@ type BACnetEventParameterChangeOfValueCivCriteriaRequirements interface {
// _BACnetEventParameterChangeOfValueCivCriteria is the data-structure of this message
type _BACnetEventParameterChangeOfValueCivCriteria struct {
- _SubType BACnetEventParameterChangeOfValueCivCriteria
+ _SubType interface {
+ BACnetEventParameterChangeOfValueCivCriteriaContract
+ BACnetEventParameterChangeOfValueCivCriteriaRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameter.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameter.go
index fa188be626a..2cdd07c75be 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameter.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameter.go
@@ -69,7 +69,10 @@ type BACnetFaultParameterRequirements interface {
// _BACnetFaultParameter is the data-structure of this message
type _BACnetFaultParameter struct {
- _SubType BACnetFaultParameter
+ _SubType interface {
+ BACnetFaultParameterContract
+ BACnetFaultParameterRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultExtendedParametersEntry.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultExtendedParametersEntry.go
index 89afb963522..35467c1711a 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultExtendedParametersEntry.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultExtendedParametersEntry.go
@@ -73,7 +73,10 @@ type BACnetFaultParameterFaultExtendedParametersEntryRequirements interface {
// _BACnetFaultParameterFaultExtendedParametersEntry is the data-structure of this message
type _BACnetFaultParameterFaultExtendedParametersEntry struct {
- _SubType BACnetFaultParameterFaultExtendedParametersEntry
+ _SubType interface {
+ BACnetFaultParameterFaultExtendedParametersEntryContract
+ BACnetFaultParameterFaultExtendedParametersEntryRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMaxNormalValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMaxNormalValue.go
index d48e06240f2..e4b7ecdc3c8 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMaxNormalValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMaxNormalValue.go
@@ -75,7 +75,10 @@ type BACnetFaultParameterFaultOutOfRangeMaxNormalValueRequirements interface {
// _BACnetFaultParameterFaultOutOfRangeMaxNormalValue is the data-structure of this message
type _BACnetFaultParameterFaultOutOfRangeMaxNormalValue struct {
- _SubType BACnetFaultParameterFaultOutOfRangeMaxNormalValue
+ _SubType interface {
+ BACnetFaultParameterFaultOutOfRangeMaxNormalValueContract
+ BACnetFaultParameterFaultOutOfRangeMaxNormalValueRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMinNormalValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMinNormalValue.go
index 9ff68f44159..8af08eaacee 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMinNormalValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetFaultParameterFaultOutOfRangeMinNormalValue.go
@@ -75,7 +75,10 @@ type BACnetFaultParameterFaultOutOfRangeMinNormalValueRequirements interface {
// _BACnetFaultParameterFaultOutOfRangeMinNormalValue is the data-structure of this message
type _BACnetFaultParameterFaultOutOfRangeMinNormalValue struct {
- _SubType BACnetFaultParameterFaultOutOfRangeMinNormalValue
+ _SubType interface {
+ BACnetFaultParameterFaultOutOfRangeMinNormalValueContract
+ BACnetFaultParameterFaultOutOfRangeMinNormalValueRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetHostAddress.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetHostAddress.go
index af7a1ceb526..241f2ab1f75 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetHostAddress.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetHostAddress.go
@@ -69,7 +69,10 @@ type BACnetHostAddressRequirements interface {
// _BACnetHostAddress is the data-structure of this message
type _BACnetHostAddress struct {
- _SubType BACnetHostAddress
+ _SubType interface {
+ BACnetHostAddressContract
+ BACnetHostAddressRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetLandingCallStatusCommand.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetLandingCallStatusCommand.go
index a1da5ce03f7..e5a7d8e526c 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetLandingCallStatusCommand.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetLandingCallStatusCommand.go
@@ -69,7 +69,10 @@ type BACnetLandingCallStatusCommandRequirements interface {
// _BACnetLandingCallStatusCommand is the data-structure of this message
type _BACnetLandingCallStatusCommand struct {
- _SubType BACnetLandingCallStatusCommand
+ _SubType interface {
+ BACnetLandingCallStatusCommandContract
+ BACnetLandingCallStatusCommandRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetLogData.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetLogData.go
index b8f499b74da..b6d655c5ec0 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetLogData.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetLogData.go
@@ -75,7 +75,10 @@ type BACnetLogDataRequirements interface {
// _BACnetLogData is the data-structure of this message
type _BACnetLogData struct {
- _SubType BACnetLogData
+ _SubType interface {
+ BACnetLogDataContract
+ BACnetLogDataRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetLogDataLogDataEntry.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetLogDataLogDataEntry.go
index 8b8a397ac04..f88b80b7c7c 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetLogDataLogDataEntry.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetLogDataLogDataEntry.go
@@ -69,7 +69,10 @@ type BACnetLogDataLogDataEntryRequirements interface {
// _BACnetLogDataLogDataEntry is the data-structure of this message
type _BACnetLogDataLogDataEntry struct {
- _SubType BACnetLogDataLogDataEntry
+ _SubType interface {
+ BACnetLogDataLogDataEntryContract
+ BACnetLogDataLogDataEntryRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetLogRecordLogDatum.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetLogRecordLogDatum.go
index a1783dd0bc9..98041c53247 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetLogRecordLogDatum.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetLogRecordLogDatum.go
@@ -75,7 +75,10 @@ type BACnetLogRecordLogDatumRequirements interface {
// _BACnetLogRecordLogDatum is the data-structure of this message
type _BACnetLogRecordLogDatum struct {
- _SubType BACnetLogRecordLogDatum
+ _SubType interface {
+ BACnetLogRecordLogDatumContract
+ BACnetLogRecordLogDatumRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParameters.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParameters.go
index 3ff0d51d10b..e4203f0272d 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParameters.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParameters.go
@@ -77,7 +77,10 @@ type BACnetNotificationParametersRequirements interface {
// _BACnetNotificationParameters is the data-structure of this message
type _BACnetNotificationParameters struct {
- _SubType BACnetNotificationParameters
+ _SubType interface {
+ BACnetNotificationParametersContract
+ BACnetNotificationParametersRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfDiscreteValueNewValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfDiscreteValueNewValue.go
index b173a3a37b8..3c944fccc54 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfDiscreteValueNewValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfDiscreteValueNewValue.go
@@ -79,7 +79,10 @@ type BACnetNotificationParametersChangeOfDiscreteValueNewValueRequirements inter
// _BACnetNotificationParametersChangeOfDiscreteValueNewValue is the data-structure of this message
type _BACnetNotificationParametersChangeOfDiscreteValueNewValue struct {
- _SubType BACnetNotificationParametersChangeOfDiscreteValueNewValue
+ _SubType interface {
+ BACnetNotificationParametersChangeOfDiscreteValueNewValueContract
+ BACnetNotificationParametersChangeOfDiscreteValueNewValueRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfValueNewValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfValueNewValue.go
index 6e347b87aea..f7821bec9a9 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfValueNewValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetNotificationParametersChangeOfValueNewValue.go
@@ -75,7 +75,10 @@ type BACnetNotificationParametersChangeOfValueNewValueRequirements interface {
// _BACnetNotificationParametersChangeOfValueNewValue is the data-structure of this message
type _BACnetNotificationParametersChangeOfValueNewValue struct {
- _SubType BACnetNotificationParametersChangeOfValueNewValue
+ _SubType interface {
+ BACnetNotificationParametersChangeOfValueNewValueContract
+ BACnetNotificationParametersChangeOfValueNewValueRequirements
+ }
OpeningTag BACnetOpeningTag
PeekedTagHeader BACnetTagHeader
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalBinaryPV.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalBinaryPV.go
index 4b2f96b9a67..be99aa3d27c 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalBinaryPV.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalBinaryPV.go
@@ -69,7 +69,10 @@ type BACnetOptionalBinaryPVRequirements interface {
// _BACnetOptionalBinaryPV is the data-structure of this message
type _BACnetOptionalBinaryPV struct {
- _SubType BACnetOptionalBinaryPV
+ _SubType interface {
+ BACnetOptionalBinaryPVContract
+ BACnetOptionalBinaryPVRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalCharacterString.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalCharacterString.go
index 41ca5e5040e..5dfe06ef3d1 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalCharacterString.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalCharacterString.go
@@ -69,7 +69,10 @@ type BACnetOptionalCharacterStringRequirements interface {
// _BACnetOptionalCharacterString is the data-structure of this message
type _BACnetOptionalCharacterString struct {
- _SubType BACnetOptionalCharacterString
+ _SubType interface {
+ BACnetOptionalCharacterStringContract
+ BACnetOptionalCharacterStringRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalREAL.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalREAL.go
index dee9c82067a..d64b2ac554d 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalREAL.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalREAL.go
@@ -69,7 +69,10 @@ type BACnetOptionalREALRequirements interface {
// _BACnetOptionalREAL is the data-structure of this message
type _BACnetOptionalREAL struct {
- _SubType BACnetOptionalREAL
+ _SubType interface {
+ BACnetOptionalREALContract
+ BACnetOptionalREALRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalUnsigned.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalUnsigned.go
index 4174c0ed86b..f7feabb43d0 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalUnsigned.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetOptionalUnsigned.go
@@ -69,7 +69,10 @@ type BACnetOptionalUnsignedRequirements interface {
// _BACnetOptionalUnsigned is the data-structure of this message
type _BACnetOptionalUnsigned struct {
- _SubType BACnetOptionalUnsigned
+ _SubType interface {
+ BACnetOptionalUnsignedContract
+ BACnetOptionalUnsignedRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetPriorityValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetPriorityValue.go
index e5c29bb70e8..ac7a44cca99 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetPriorityValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetPriorityValue.go
@@ -75,7 +75,10 @@ type BACnetPriorityValueRequirements interface {
// _BACnetPriorityValue is the data-structure of this message
type _BACnetPriorityValue struct {
- _SubType BACnetPriorityValue
+ _SubType interface {
+ BACnetPriorityValueContract
+ BACnetPriorityValueRequirements
+ }
PeekedTagHeader BACnetTagHeader
// Arguments.
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetProcessIdSelection.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetProcessIdSelection.go
index f3860b9d071..61d2db35584 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetProcessIdSelection.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetProcessIdSelection.go
@@ -69,7 +69,10 @@ type BACnetProcessIdSelectionRequirements interface {
// _BACnetProcessIdSelection is the data-structure of this message
type _BACnetProcessIdSelection struct {
- _SubType BACnetProcessIdSelection
+ _SubType interface {
+ BACnetProcessIdSelectionContract
+ BACnetProcessIdSelectionRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyAccessResultAccessResult.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyAccessResultAccessResult.go
index 8b7f48c7164..1a46b638377 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyAccessResultAccessResult.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyAccessResultAccessResult.go
@@ -75,7 +75,10 @@ type BACnetPropertyAccessResultAccessResultRequirements interface {
// _BACnetPropertyAccessResultAccessResult is the data-structure of this message
type _BACnetPropertyAccessResultAccessResult struct {
- _SubType BACnetPropertyAccessResultAccessResult
+ _SubType interface {
+ BACnetPropertyAccessResultAccessResultContract
+ BACnetPropertyAccessResultAccessResultRequirements
+ }
PeekedTagHeader BACnetTagHeader
// Arguments.
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyStates.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyStates.go
index f3a1b045dfc..45b2a4077f3 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyStates.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetPropertyStates.go
@@ -69,7 +69,10 @@ type BACnetPropertyStatesRequirements interface {
// _BACnetPropertyStates is the data-structure of this message
type _BACnetPropertyStates struct {
- _SubType BACnetPropertyStates
+ _SubType interface {
+ BACnetPropertyStatesContract
+ BACnetPropertyStatesRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetRecipient.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetRecipient.go
index 671b61c9d86..bf9efa4e703 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetRecipient.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetRecipient.go
@@ -69,7 +69,10 @@ type BACnetRecipientRequirements interface {
// _BACnetRecipient is the data-structure of this message
type _BACnetRecipient struct {
- _SubType BACnetRecipient
+ _SubType interface {
+ BACnetRecipientContract
+ BACnetRecipientRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetScale.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetScale.go
index 73212d2a3ed..10ae0b153ae 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetScale.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetScale.go
@@ -69,7 +69,10 @@ type BACnetScaleRequirements interface {
// _BACnetScale is the data-structure of this message
type _BACnetScale struct {
- _SubType BACnetScale
+ _SubType interface {
+ BACnetScaleContract
+ BACnetScaleRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAck.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAck.go
index e7e12edc4e7..57a3f3ac3f6 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAck.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAck.go
@@ -69,7 +69,10 @@ type BACnetServiceAckRequirements interface {
// _BACnetServiceAck is the data-structure of this message
type _BACnetServiceAck struct {
- _SubType BACnetServiceAck
+ _SubType interface {
+ BACnetServiceAckContract
+ BACnetServiceAckRequirements
+ }
// Arguments.
ServiceAckLength uint32
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAckAtomicReadFileStreamOrRecord.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAckAtomicReadFileStreamOrRecord.go
index d2cea00d65e..d632ea20423 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAckAtomicReadFileStreamOrRecord.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetServiceAckAtomicReadFileStreamOrRecord.go
@@ -73,7 +73,10 @@ type BACnetServiceAckAtomicReadFileStreamOrRecordRequirements interface {
// _BACnetServiceAckAtomicReadFileStreamOrRecord is the data-structure of this message
type _BACnetServiceAckAtomicReadFileStreamOrRecord struct {
- _SubType BACnetServiceAckAtomicReadFileStreamOrRecord
+ _SubType interface {
+ BACnetServiceAckAtomicReadFileStreamOrRecordContract
+ BACnetServiceAckAtomicReadFileStreamOrRecordRequirements
+ }
PeekedTagHeader BACnetTagHeader
OpeningTag BACnetOpeningTag
ClosingTag BACnetClosingTag
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetShedLevel.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetShedLevel.go
index 4205d55f845..44a57c9b3b7 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetShedLevel.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetShedLevel.go
@@ -69,7 +69,10 @@ type BACnetShedLevelRequirements interface {
// _BACnetShedLevel is the data-structure of this message
type _BACnetShedLevel struct {
- _SubType BACnetShedLevel
+ _SubType interface {
+ BACnetShedLevelContract
+ BACnetShedLevelRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetSpecialEventPeriod.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetSpecialEventPeriod.go
index 7d9851c6874..fc318d47c1d 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetSpecialEventPeriod.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetSpecialEventPeriod.go
@@ -69,7 +69,10 @@ type BACnetSpecialEventPeriodRequirements interface {
// _BACnetSpecialEventPeriod is the data-structure of this message
type _BACnetSpecialEventPeriod struct {
- _SubType BACnetSpecialEventPeriod
+ _SubType interface {
+ BACnetSpecialEventPeriodContract
+ BACnetSpecialEventPeriodRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetTimeStamp.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetTimeStamp.go
index 477106cbf5a..9c44205e1b3 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetTimeStamp.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetTimeStamp.go
@@ -69,7 +69,10 @@ type BACnetTimeStampRequirements interface {
// _BACnetTimeStamp is the data-structure of this message
type _BACnetTimeStamp struct {
- _SubType BACnetTimeStamp
+ _SubType interface {
+ BACnetTimeStampContract
+ BACnetTimeStampRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetTimerStateChangeValue.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetTimerStateChangeValue.go
index ddcab099d77..cbd8df0e8de 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetTimerStateChangeValue.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetTimerStateChangeValue.go
@@ -75,7 +75,10 @@ type BACnetTimerStateChangeValueRequirements interface {
// _BACnetTimerStateChangeValue is the data-structure of this message
type _BACnetTimerStateChangeValue struct {
- _SubType BACnetTimerStateChangeValue
+ _SubType interface {
+ BACnetTimerStateChangeValueContract
+ BACnetTimerStateChangeValueRequirements
+ }
PeekedTagHeader BACnetTagHeader
// Arguments.
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequest.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequest.go
index e1b0edab542..97a326dc027 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequest.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequest.go
@@ -67,7 +67,10 @@ type BACnetUnconfirmedServiceRequestRequirements interface {
// _BACnetUnconfirmedServiceRequest is the data-structure of this message
type _BACnetUnconfirmedServiceRequest struct {
- _SubType BACnetUnconfirmedServiceRequest
+ _SubType interface {
+ BACnetUnconfirmedServiceRequestContract
+ BACnetUnconfirmedServiceRequestRequirements
+ }
// Arguments.
ServiceRequestLength uint16
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHasObject.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHasObject.go
index ea6d1c741d1..ca5e211be67 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHasObject.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHasObject.go
@@ -69,7 +69,10 @@ type BACnetUnconfirmedServiceRequestWhoHasObjectRequirements interface {
// _BACnetUnconfirmedServiceRequestWhoHasObject is the data-structure of this message
type _BACnetUnconfirmedServiceRequestWhoHasObject struct {
- _SubType BACnetUnconfirmedServiceRequestWhoHasObject
+ _SubType interface {
+ BACnetUnconfirmedServiceRequestWhoHasObjectContract
+ BACnetUnconfirmedServiceRequestWhoHasObjectRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BACnetValueSource.go b/plc4go/protocols/bacnetip/readwrite/model/BACnetValueSource.go
index 71df50e7b55..3879b975dc8 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BACnetValueSource.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BACnetValueSource.go
@@ -69,7 +69,10 @@ type BACnetValueSourceRequirements interface {
// _BACnetValueSource is the data-structure of this message
type _BACnetValueSource struct {
- _SubType BACnetValueSource
+ _SubType interface {
+ BACnetValueSourceContract
+ BACnetValueSourceRequirements
+ }
PeekedTagHeader BACnetTagHeader
}
diff --git a/plc4go/protocols/bacnetip/readwrite/model/BVLC.go b/plc4go/protocols/bacnetip/readwrite/model/BVLC.go
index e61d8f794f2..681df9b8fab 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/BVLC.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/BVLC.go
@@ -72,7 +72,10 @@ type BVLCRequirements interface {
// _BVLC is the data-structure of this message
type _BVLC struct {
- _SubType BVLC
+ _SubType interface {
+ BVLCContract
+ BVLCRequirements
+ }
}
var _ BVLCContract = (*_BVLC)(nil)
diff --git a/plc4go/protocols/bacnetip/readwrite/model/NLM.go b/plc4go/protocols/bacnetip/readwrite/model/NLM.go
index 4bcdd0a7971..2f10f9747bd 100644
--- a/plc4go/protocols/bacnetip/readwrite/model/NLM.go
+++ b/plc4go/protocols/bacnetip/readwrite/model/NLM.go
@@ -71,7 +71,10 @@ type NLMRequirements interface {
// _NLM is the data-structure of this message
type _NLM struct {
- _SubType NLM
+ _SubType interface {
+ NLMContract
+ NLMRequirements
+ }
// Arguments.
ApduLength uint16
diff --git a/plc4go/protocols/cbus/readwrite/model/AccessControlData.go b/plc4go/protocols/cbus/readwrite/model/AccessControlData.go
index d84d87bbba0..e56650cff5d 100644
--- a/plc4go/protocols/cbus/readwrite/model/AccessControlData.go
+++ b/plc4go/protocols/cbus/readwrite/model/AccessControlData.go
@@ -73,7 +73,10 @@ type AccessControlDataRequirements interface {
// _AccessControlData is the data-structure of this message
type _AccessControlData struct {
- _SubType AccessControlData
+ _SubType interface {
+ AccessControlDataContract
+ AccessControlDataRequirements
+ }
CommandTypeContainer AccessControlCommandTypeContainer
NetworkId byte
AccessPointId byte
diff --git a/plc4go/protocols/cbus/readwrite/model/AirConditioningData.go b/plc4go/protocols/cbus/readwrite/model/AirConditioningData.go
index 224150f122b..8a0f8e6b969 100644
--- a/plc4go/protocols/cbus/readwrite/model/AirConditioningData.go
+++ b/plc4go/protocols/cbus/readwrite/model/AirConditioningData.go
@@ -69,7 +69,10 @@ type AirConditioningDataRequirements interface {
// _AirConditioningData is the data-structure of this message
type _AirConditioningData struct {
- _SubType AirConditioningData
+ _SubType interface {
+ AirConditioningDataContract
+ AirConditioningDataRequirements
+ }
CommandTypeContainer AirConditioningCommandTypeContainer
}
diff --git a/plc4go/protocols/cbus/readwrite/model/CALData.go b/plc4go/protocols/cbus/readwrite/model/CALData.go
index 6a45e988a67..3ba9ff66c9e 100644
--- a/plc4go/protocols/cbus/readwrite/model/CALData.go
+++ b/plc4go/protocols/cbus/readwrite/model/CALData.go
@@ -77,7 +77,10 @@ type CALDataRequirements interface {
// _CALData is the data-structure of this message
type _CALData struct {
- _SubType CALData
+ _SubType interface {
+ CALDataContract
+ CALDataRequirements
+ }
CommandTypeContainer CALCommandTypeContainer
AdditionalData CALData
diff --git a/plc4go/protocols/cbus/readwrite/model/CALReply.go b/plc4go/protocols/cbus/readwrite/model/CALReply.go
index a99708b4548..6028b320ad9 100644
--- a/plc4go/protocols/cbus/readwrite/model/CALReply.go
+++ b/plc4go/protocols/cbus/readwrite/model/CALReply.go
@@ -73,9 +73,12 @@ type CALReplyRequirements interface {
// _CALReply is the data-structure of this message
type _CALReply struct {
- _SubType CALReply
- CalType byte
- CalData CALData
+ _SubType interface {
+ CALReplyContract
+ CALReplyRequirements
+ }
+ CalType byte
+ CalData CALData
// Arguments.
CBusOptions CBusOptions
diff --git a/plc4go/protocols/cbus/readwrite/model/CBusCommand.go b/plc4go/protocols/cbus/readwrite/model/CBusCommand.go
index 16600cd4bdd..ac9f01a4ca4 100644
--- a/plc4go/protocols/cbus/readwrite/model/CBusCommand.go
+++ b/plc4go/protocols/cbus/readwrite/model/CBusCommand.go
@@ -75,8 +75,11 @@ type CBusCommandRequirements interface {
// _CBusCommand is the data-structure of this message
type _CBusCommand struct {
- _SubType CBusCommand
- Header CBusHeader
+ _SubType interface {
+ CBusCommandContract
+ CBusCommandRequirements
+ }
+ Header CBusHeader
// Arguments.
CBusOptions CBusOptions
diff --git a/plc4go/protocols/cbus/readwrite/model/CBusMessage.go b/plc4go/protocols/cbus/readwrite/model/CBusMessage.go
index c3641c34dd6..1b6da58c982 100644
--- a/plc4go/protocols/cbus/readwrite/model/CBusMessage.go
+++ b/plc4go/protocols/cbus/readwrite/model/CBusMessage.go
@@ -67,7 +67,10 @@ type CBusMessageRequirements interface {
// _CBusMessage is the data-structure of this message
type _CBusMessage struct {
- _SubType CBusMessage
+ _SubType interface {
+ CBusMessageContract
+ CBusMessageRequirements
+ }
// Arguments.
RequestContext RequestContext
diff --git a/plc4go/protocols/cbus/readwrite/model/CBusPointToMultiPointCommand.go b/plc4go/protocols/cbus/readwrite/model/CBusPointToMultiPointCommand.go
index e1e8c2c2ce1..df29a8ae452 100644
--- a/plc4go/protocols/cbus/readwrite/model/CBusPointToMultiPointCommand.go
+++ b/plc4go/protocols/cbus/readwrite/model/CBusPointToMultiPointCommand.go
@@ -69,7 +69,10 @@ type CBusPointToMultiPointCommandRequirements interface {
// _CBusPointToMultiPointCommand is the data-structure of this message
type _CBusPointToMultiPointCommand struct {
- _SubType CBusPointToMultiPointCommand
+ _SubType interface {
+ CBusPointToMultiPointCommandContract
+ CBusPointToMultiPointCommandRequirements
+ }
PeekedApplication byte
// Arguments.
diff --git a/plc4go/protocols/cbus/readwrite/model/CBusPointToPointCommand.go b/plc4go/protocols/cbus/readwrite/model/CBusPointToPointCommand.go
index 8b82e1e90eb..ce6f918931e 100644
--- a/plc4go/protocols/cbus/readwrite/model/CBusPointToPointCommand.go
+++ b/plc4go/protocols/cbus/readwrite/model/CBusPointToPointCommand.go
@@ -73,7 +73,10 @@ type CBusPointToPointCommandRequirements interface {
// _CBusPointToPointCommand is the data-structure of this message
type _CBusPointToPointCommand struct {
- _SubType CBusPointToPointCommand
+ _SubType interface {
+ CBusPointToPointCommandContract
+ CBusPointToPointCommandRequirements
+ }
BridgeAddressCountPeek uint16
CalData CALData
diff --git a/plc4go/protocols/cbus/readwrite/model/CBusPointToPointToMultiPointCommand.go b/plc4go/protocols/cbus/readwrite/model/CBusPointToPointToMultiPointCommand.go
index 23096bb6c7d..42eaba46ffa 100644
--- a/plc4go/protocols/cbus/readwrite/model/CBusPointToPointToMultiPointCommand.go
+++ b/plc4go/protocols/cbus/readwrite/model/CBusPointToPointToMultiPointCommand.go
@@ -73,7 +73,10 @@ type CBusPointToPointToMultiPointCommandRequirements interface {
// _CBusPointToPointToMultiPointCommand is the data-structure of this message
type _CBusPointToPointToMultiPointCommand struct {
- _SubType CBusPointToPointToMultiPointCommand
+ _SubType interface {
+ CBusPointToPointToMultiPointCommandContract
+ CBusPointToPointToMultiPointCommandRequirements
+ }
BridgeAddress BridgeAddress
NetworkRoute NetworkRoute
PeekedApplication byte
diff --git a/plc4go/protocols/cbus/readwrite/model/ClockAndTimekeepingData.go b/plc4go/protocols/cbus/readwrite/model/ClockAndTimekeepingData.go
index a6277e725bf..9d917556ea0 100644
--- a/plc4go/protocols/cbus/readwrite/model/ClockAndTimekeepingData.go
+++ b/plc4go/protocols/cbus/readwrite/model/ClockAndTimekeepingData.go
@@ -73,7 +73,10 @@ type ClockAndTimekeepingDataRequirements interface {
// _ClockAndTimekeepingData is the data-structure of this message
type _ClockAndTimekeepingData struct {
- _SubType ClockAndTimekeepingData
+ _SubType interface {
+ ClockAndTimekeepingDataContract
+ ClockAndTimekeepingDataRequirements
+ }
CommandTypeContainer ClockAndTimekeepingCommandTypeContainer
Argument byte
}
diff --git a/plc4go/protocols/cbus/readwrite/model/EncodedReply.go b/plc4go/protocols/cbus/readwrite/model/EncodedReply.go
index 7958c6df83e..6b127f565e8 100644
--- a/plc4go/protocols/cbus/readwrite/model/EncodedReply.go
+++ b/plc4go/protocols/cbus/readwrite/model/EncodedReply.go
@@ -73,7 +73,10 @@ type EncodedReplyRequirements interface {
// _EncodedReply is the data-structure of this message
type _EncodedReply struct {
- _SubType EncodedReply
+ _SubType interface {
+ EncodedReplyContract
+ EncodedReplyRequirements
+ }
PeekedByte byte
// Arguments.
diff --git a/plc4go/protocols/cbus/readwrite/model/ErrorReportingData.go b/plc4go/protocols/cbus/readwrite/model/ErrorReportingData.go
index e4a0d4895c9..5ec87b5f894 100644
--- a/plc4go/protocols/cbus/readwrite/model/ErrorReportingData.go
+++ b/plc4go/protocols/cbus/readwrite/model/ErrorReportingData.go
@@ -69,7 +69,10 @@ type ErrorReportingDataRequirements interface {
// _ErrorReportingData is the data-structure of this message
type _ErrorReportingData struct {
- _SubType ErrorReportingData
+ _SubType interface {
+ ErrorReportingDataContract
+ ErrorReportingDataRequirements
+ }
CommandTypeContainer ErrorReportingCommandTypeContainer
}
diff --git a/plc4go/protocols/cbus/readwrite/model/ErrorReportingSystemCategoryType.go b/plc4go/protocols/cbus/readwrite/model/ErrorReportingSystemCategoryType.go
index 528dfb3b03f..8169e5e77ed 100644
--- a/plc4go/protocols/cbus/readwrite/model/ErrorReportingSystemCategoryType.go
+++ b/plc4go/protocols/cbus/readwrite/model/ErrorReportingSystemCategoryType.go
@@ -63,7 +63,10 @@ type ErrorReportingSystemCategoryTypeRequirements interface {
// _ErrorReportingSystemCategoryType is the data-structure of this message
type _ErrorReportingSystemCategoryType struct {
- _SubType ErrorReportingSystemCategoryType
+ _SubType interface {
+ ErrorReportingSystemCategoryTypeContract
+ ErrorReportingSystemCategoryTypeRequirements
+ }
}
var _ ErrorReportingSystemCategoryTypeContract = (*_ErrorReportingSystemCategoryType)(nil)
diff --git a/plc4go/protocols/cbus/readwrite/model/IdentifyReplyCommand.go b/plc4go/protocols/cbus/readwrite/model/IdentifyReplyCommand.go
index b9d6e7ccbed..251d119c9a1 100644
--- a/plc4go/protocols/cbus/readwrite/model/IdentifyReplyCommand.go
+++ b/plc4go/protocols/cbus/readwrite/model/IdentifyReplyCommand.go
@@ -65,7 +65,10 @@ type IdentifyReplyCommandRequirements interface {
// _IdentifyReplyCommand is the data-structure of this message
type _IdentifyReplyCommand struct {
- _SubType IdentifyReplyCommand
+ _SubType interface {
+ IdentifyReplyCommandContract
+ IdentifyReplyCommandRequirements
+ }
// Arguments.
NumBytes uint8
diff --git a/plc4go/protocols/cbus/readwrite/model/LevelInformation.go b/plc4go/protocols/cbus/readwrite/model/LevelInformation.go
index af501184e28..2d1c549bc3a 100644
--- a/plc4go/protocols/cbus/readwrite/model/LevelInformation.go
+++ b/plc4go/protocols/cbus/readwrite/model/LevelInformation.go
@@ -85,8 +85,11 @@ type LevelInformationRequirements interface {
// _LevelInformation is the data-structure of this message
type _LevelInformation struct {
- _SubType LevelInformation
- Raw uint16
+ _SubType interface {
+ LevelInformationContract
+ LevelInformationRequirements
+ }
+ Raw uint16
}
var _ LevelInformationContract = (*_LevelInformation)(nil)
diff --git a/plc4go/protocols/cbus/readwrite/model/LightingData.go b/plc4go/protocols/cbus/readwrite/model/LightingData.go
index df20ef9a31f..81d8d9e0b44 100644
--- a/plc4go/protocols/cbus/readwrite/model/LightingData.go
+++ b/plc4go/protocols/cbus/readwrite/model/LightingData.go
@@ -69,7 +69,10 @@ type LightingDataRequirements interface {
// _LightingData is the data-structure of this message
type _LightingData struct {
- _SubType LightingData
+ _SubType interface {
+ LightingDataContract
+ LightingDataRequirements
+ }
CommandTypeContainer LightingCommandTypeContainer
}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeasurementData.go b/plc4go/protocols/cbus/readwrite/model/MeasurementData.go
index de7f8500216..df4f3d54181 100644
--- a/plc4go/protocols/cbus/readwrite/model/MeasurementData.go
+++ b/plc4go/protocols/cbus/readwrite/model/MeasurementData.go
@@ -69,7 +69,10 @@ type MeasurementDataRequirements interface {
// _MeasurementData is the data-structure of this message
type _MeasurementData struct {
- _SubType MeasurementData
+ _SubType interface {
+ MeasurementDataContract
+ MeasurementDataRequirements
+ }
CommandTypeContainer MeasurementCommandTypeContainer
}
diff --git a/plc4go/protocols/cbus/readwrite/model/MediaTransportControlData.go b/plc4go/protocols/cbus/readwrite/model/MediaTransportControlData.go
index a7c7c03e17a..a7e31638da5 100644
--- a/plc4go/protocols/cbus/readwrite/model/MediaTransportControlData.go
+++ b/plc4go/protocols/cbus/readwrite/model/MediaTransportControlData.go
@@ -71,7 +71,10 @@ type MediaTransportControlDataRequirements interface {
// _MediaTransportControlData is the data-structure of this message
type _MediaTransportControlData struct {
- _SubType MediaTransportControlData
+ _SubType interface {
+ MediaTransportControlDataContract
+ MediaTransportControlDataRequirements
+ }
CommandTypeContainer MediaTransportControlCommandTypeContainer
MediaLinkGroup byte
}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringData.go b/plc4go/protocols/cbus/readwrite/model/MeteringData.go
index 139d6ff172b..4000ac5e217 100644
--- a/plc4go/protocols/cbus/readwrite/model/MeteringData.go
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringData.go
@@ -73,7 +73,10 @@ type MeteringDataRequirements interface {
// _MeteringData is the data-structure of this message
type _MeteringData struct {
- _SubType MeteringData
+ _SubType interface {
+ MeteringDataContract
+ MeteringDataRequirements
+ }
CommandTypeContainer MeteringCommandTypeContainer
Argument byte
}
diff --git a/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go b/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go
index 75dd4c9245c..69fb7c73cdd 100644
--- a/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go
+++ b/plc4go/protocols/cbus/readwrite/model/MonitoredSAL.go
@@ -69,8 +69,11 @@ type MonitoredSALRequirements interface {
// _MonitoredSAL is the data-structure of this message
type _MonitoredSAL struct {
- _SubType MonitoredSAL
- SalType byte
+ _SubType interface {
+ MonitoredSALContract
+ MonitoredSALRequirements
+ }
+ SalType byte
// Arguments.
CBusOptions CBusOptions
diff --git a/plc4go/protocols/cbus/readwrite/model/ParameterValue.go b/plc4go/protocols/cbus/readwrite/model/ParameterValue.go
index afed6512099..dba765ffb71 100644
--- a/plc4go/protocols/cbus/readwrite/model/ParameterValue.go
+++ b/plc4go/protocols/cbus/readwrite/model/ParameterValue.go
@@ -65,7 +65,10 @@ type ParameterValueRequirements interface {
// _ParameterValue is the data-structure of this message
type _ParameterValue struct {
- _SubType ParameterValue
+ _SubType interface {
+ ParameterValueContract
+ ParameterValueRequirements
+ }
// Arguments.
NumBytes uint8
diff --git a/plc4go/protocols/cbus/readwrite/model/Reply.go b/plc4go/protocols/cbus/readwrite/model/Reply.go
index 3fef6b24928..0418b3d229f 100644
--- a/plc4go/protocols/cbus/readwrite/model/Reply.go
+++ b/plc4go/protocols/cbus/readwrite/model/Reply.go
@@ -71,7 +71,10 @@ type ReplyRequirements interface {
// _Reply is the data-structure of this message
type _Reply struct {
- _SubType Reply
+ _SubType interface {
+ ReplyContract
+ ReplyRequirements
+ }
PeekedByte byte
// Arguments.
diff --git a/plc4go/protocols/cbus/readwrite/model/ReplyOrConfirmation.go b/plc4go/protocols/cbus/readwrite/model/ReplyOrConfirmation.go
index de65b68dacf..53b4b997a01 100644
--- a/plc4go/protocols/cbus/readwrite/model/ReplyOrConfirmation.go
+++ b/plc4go/protocols/cbus/readwrite/model/ReplyOrConfirmation.go
@@ -75,7 +75,10 @@ type ReplyOrConfirmationRequirements interface {
// _ReplyOrConfirmation is the data-structure of this message
type _ReplyOrConfirmation struct {
- _SubType ReplyOrConfirmation
+ _SubType interface {
+ ReplyOrConfirmationContract
+ ReplyOrConfirmationRequirements
+ }
PeekedByte byte
// Arguments.
diff --git a/plc4go/protocols/cbus/readwrite/model/Request.go b/plc4go/protocols/cbus/readwrite/model/Request.go
index 72b721bcd3c..52465e73dff 100644
--- a/plc4go/protocols/cbus/readwrite/model/Request.go
+++ b/plc4go/protocols/cbus/readwrite/model/Request.go
@@ -79,7 +79,10 @@ type RequestRequirements interface {
// _Request is the data-structure of this message
type _Request struct {
- _SubType Request
+ _SubType interface {
+ RequestContract
+ RequestRequirements
+ }
PeekedByte RequestType
StartingCR *RequestType
ResetMode *RequestType
diff --git a/plc4go/protocols/cbus/readwrite/model/SALData.go b/plc4go/protocols/cbus/readwrite/model/SALData.go
index 26d3a9a7d54..8b09aa9a257 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALData.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALData.go
@@ -67,8 +67,11 @@ type SALDataRequirements interface {
// _SALData is the data-structure of this message
type _SALData struct {
- _SubType SALData
- SalData SALData
+ _SubType interface {
+ SALDataContract
+ SALDataRequirements
+ }
+ SalData SALData
}
var _ SALDataContract = (*_SALData)(nil)
diff --git a/plc4go/protocols/cbus/readwrite/model/SecurityData.go b/plc4go/protocols/cbus/readwrite/model/SecurityData.go
index 384444e15aa..db3f4f412a1 100644
--- a/plc4go/protocols/cbus/readwrite/model/SecurityData.go
+++ b/plc4go/protocols/cbus/readwrite/model/SecurityData.go
@@ -73,7 +73,10 @@ type SecurityDataRequirements interface {
// _SecurityData is the data-structure of this message
type _SecurityData struct {
- _SubType SecurityData
+ _SubType interface {
+ SecurityDataContract
+ SecurityDataRequirements
+ }
CommandTypeContainer SecurityCommandTypeContainer
Argument byte
}
diff --git a/plc4go/protocols/cbus/readwrite/model/StatusRequest.go b/plc4go/protocols/cbus/readwrite/model/StatusRequest.go
index 7a6ab37ab9c..5f3037f8f5b 100644
--- a/plc4go/protocols/cbus/readwrite/model/StatusRequest.go
+++ b/plc4go/protocols/cbus/readwrite/model/StatusRequest.go
@@ -67,7 +67,10 @@ type StatusRequestRequirements interface {
// _StatusRequest is the data-structure of this message
type _StatusRequest struct {
- _SubType StatusRequest
+ _SubType interface {
+ StatusRequestContract
+ StatusRequestRequirements
+ }
StatusType byte
}
diff --git a/plc4go/protocols/cbus/readwrite/model/TelephonyData.go b/plc4go/protocols/cbus/readwrite/model/TelephonyData.go
index 5344c44e760..e125919c194 100644
--- a/plc4go/protocols/cbus/readwrite/model/TelephonyData.go
+++ b/plc4go/protocols/cbus/readwrite/model/TelephonyData.go
@@ -73,7 +73,10 @@ type TelephonyDataRequirements interface {
// _TelephonyData is the data-structure of this message
type _TelephonyData struct {
- _SubType TelephonyData
+ _SubType interface {
+ TelephonyDataContract
+ TelephonyDataRequirements
+ }
CommandTypeContainer TelephonyCommandTypeContainer
Argument byte
}
diff --git a/plc4go/protocols/cbus/readwrite/model/TriggerControlData.go b/plc4go/protocols/cbus/readwrite/model/TriggerControlData.go
index 113eccaa440..ad53d0880eb 100644
--- a/plc4go/protocols/cbus/readwrite/model/TriggerControlData.go
+++ b/plc4go/protocols/cbus/readwrite/model/TriggerControlData.go
@@ -73,7 +73,10 @@ type TriggerControlDataRequirements interface {
// _TriggerControlData is the data-structure of this message
type _TriggerControlData struct {
- _SubType TriggerControlData
+ _SubType interface {
+ TriggerControlDataContract
+ TriggerControlDataRequirements
+ }
CommandTypeContainer TriggerControlCommandTypeContainer
TriggerGroup byte
}
diff --git a/plc4go/protocols/df1/readwrite/model/DF1Command.go b/plc4go/protocols/df1/readwrite/model/DF1Command.go
index e047da34e3e..22c48c3eaa3 100644
--- a/plc4go/protocols/df1/readwrite/model/DF1Command.go
+++ b/plc4go/protocols/df1/readwrite/model/DF1Command.go
@@ -69,7 +69,10 @@ type DF1CommandRequirements interface {
// _DF1Command is the data-structure of this message
type _DF1Command struct {
- _SubType DF1Command
+ _SubType interface {
+ DF1CommandContract
+ DF1CommandRequirements
+ }
Status uint8
TransactionCounter uint16
}
diff --git a/plc4go/protocols/df1/readwrite/model/DF1Symbol.go b/plc4go/protocols/df1/readwrite/model/DF1Symbol.go
index b1434ee5290..733c71ac8b7 100644
--- a/plc4go/protocols/df1/readwrite/model/DF1Symbol.go
+++ b/plc4go/protocols/df1/readwrite/model/DF1Symbol.go
@@ -70,7 +70,10 @@ type DF1SymbolRequirements interface {
// _DF1Symbol is the data-structure of this message
type _DF1Symbol struct {
- _SubType DF1Symbol
+ _SubType interface {
+ DF1SymbolContract
+ DF1SymbolRequirements
+ }
}
var _ DF1SymbolContract = (*_DF1Symbol)(nil)
diff --git a/plc4go/protocols/eip/readwrite/model/CipService.go b/plc4go/protocols/eip/readwrite/model/CipService.go
index f27a71bbd46..9ad37c789c2 100644
--- a/plc4go/protocols/eip/readwrite/model/CipService.go
+++ b/plc4go/protocols/eip/readwrite/model/CipService.go
@@ -71,7 +71,10 @@ type CipServiceRequirements interface {
// _CipService is the data-structure of this message
type _CipService struct {
- _SubType CipService
+ _SubType interface {
+ CipServiceContract
+ CipServiceRequirements
+ }
// Arguments.
ServiceLen uint16
diff --git a/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go b/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go
index ad97c023a19..696d1e66cab 100644
--- a/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go
+++ b/plc4go/protocols/eip/readwrite/model/CommandSpecificDataItem.go
@@ -65,7 +65,10 @@ type CommandSpecificDataItemRequirements interface {
// _CommandSpecificDataItem is the data-structure of this message
type _CommandSpecificDataItem struct {
- _SubType CommandSpecificDataItem
+ _SubType interface {
+ CommandSpecificDataItemContract
+ CommandSpecificDataItemRequirements
+ }
}
var _ CommandSpecificDataItemContract = (*_CommandSpecificDataItem)(nil)
diff --git a/plc4go/protocols/eip/readwrite/model/DataSegmentType.go b/plc4go/protocols/eip/readwrite/model/DataSegmentType.go
index 28a12c656af..83c19ac6ec8 100644
--- a/plc4go/protocols/eip/readwrite/model/DataSegmentType.go
+++ b/plc4go/protocols/eip/readwrite/model/DataSegmentType.go
@@ -65,7 +65,10 @@ type DataSegmentTypeRequirements interface {
// _DataSegmentType is the data-structure of this message
type _DataSegmentType struct {
- _SubType DataSegmentType
+ _SubType interface {
+ DataSegmentTypeContract
+ DataSegmentTypeRequirements
+ }
}
var _ DataSegmentTypeContract = (*_DataSegmentType)(nil)
diff --git a/plc4go/protocols/eip/readwrite/model/EipPacket.go b/plc4go/protocols/eip/readwrite/model/EipPacket.go
index 36db6dda43d..73a7a264558 100644
--- a/plc4go/protocols/eip/readwrite/model/EipPacket.go
+++ b/plc4go/protocols/eip/readwrite/model/EipPacket.go
@@ -77,7 +77,10 @@ type EipPacketRequirements interface {
// _EipPacket is the data-structure of this message
type _EipPacket struct {
- _SubType EipPacket
+ _SubType interface {
+ EipPacketContract
+ EipPacketRequirements
+ }
SessionHandle uint32
Status uint32
SenderContext []byte
diff --git a/plc4go/protocols/eip/readwrite/model/LogicalSegmentType.go b/plc4go/protocols/eip/readwrite/model/LogicalSegmentType.go
index 6f9bfd17fa5..7bd4cf06ce4 100644
--- a/plc4go/protocols/eip/readwrite/model/LogicalSegmentType.go
+++ b/plc4go/protocols/eip/readwrite/model/LogicalSegmentType.go
@@ -65,7 +65,10 @@ type LogicalSegmentTypeRequirements interface {
// _LogicalSegmentType is the data-structure of this message
type _LogicalSegmentType struct {
- _SubType LogicalSegmentType
+ _SubType interface {
+ LogicalSegmentTypeContract
+ LogicalSegmentTypeRequirements
+ }
}
var _ LogicalSegmentTypeContract = (*_LogicalSegmentType)(nil)
diff --git a/plc4go/protocols/eip/readwrite/model/PathSegment.go b/plc4go/protocols/eip/readwrite/model/PathSegment.go
index 27a4eabdd13..7417ea2244a 100644
--- a/plc4go/protocols/eip/readwrite/model/PathSegment.go
+++ b/plc4go/protocols/eip/readwrite/model/PathSegment.go
@@ -65,7 +65,10 @@ type PathSegmentRequirements interface {
// _PathSegment is the data-structure of this message
type _PathSegment struct {
- _SubType PathSegment
+ _SubType interface {
+ PathSegmentContract
+ PathSegmentRequirements
+ }
}
var _ PathSegmentContract = (*_PathSegment)(nil)
diff --git a/plc4go/protocols/eip/readwrite/model/PortSegmentType.go b/plc4go/protocols/eip/readwrite/model/PortSegmentType.go
index a8431bf8595..df3b9823ba1 100644
--- a/plc4go/protocols/eip/readwrite/model/PortSegmentType.go
+++ b/plc4go/protocols/eip/readwrite/model/PortSegmentType.go
@@ -65,7 +65,10 @@ type PortSegmentTypeRequirements interface {
// _PortSegmentType is the data-structure of this message
type _PortSegmentType struct {
- _SubType PortSegmentType
+ _SubType interface {
+ PortSegmentTypeContract
+ PortSegmentTypeRequirements
+ }
}
var _ PortSegmentTypeContract = (*_PortSegmentType)(nil)
diff --git a/plc4go/protocols/eip/readwrite/model/TypeId.go b/plc4go/protocols/eip/readwrite/model/TypeId.go
index 4932978b9dd..8c5a76883c8 100644
--- a/plc4go/protocols/eip/readwrite/model/TypeId.go
+++ b/plc4go/protocols/eip/readwrite/model/TypeId.go
@@ -65,7 +65,10 @@ type TypeIdRequirements interface {
// _TypeId is the data-structure of this message
type _TypeId struct {
- _SubType TypeId
+ _SubType interface {
+ TypeIdContract
+ TypeIdRequirements
+ }
}
var _ TypeIdContract = (*_TypeId)(nil)
diff --git a/plc4go/protocols/firmata/readwrite/model/FirmataCommand.go b/plc4go/protocols/firmata/readwrite/model/FirmataCommand.go
index cbea6538bd3..2249f80e0f4 100644
--- a/plc4go/protocols/firmata/readwrite/model/FirmataCommand.go
+++ b/plc4go/protocols/firmata/readwrite/model/FirmataCommand.go
@@ -67,7 +67,10 @@ type FirmataCommandRequirements interface {
// _FirmataCommand is the data-structure of this message
type _FirmataCommand struct {
- _SubType FirmataCommand
+ _SubType interface {
+ FirmataCommandContract
+ FirmataCommandRequirements
+ }
// Arguments.
Response bool
diff --git a/plc4go/protocols/firmata/readwrite/model/FirmataMessage.go b/plc4go/protocols/firmata/readwrite/model/FirmataMessage.go
index cfedb2f88a4..578817597fc 100644
--- a/plc4go/protocols/firmata/readwrite/model/FirmataMessage.go
+++ b/plc4go/protocols/firmata/readwrite/model/FirmataMessage.go
@@ -69,7 +69,10 @@ type FirmataMessageRequirements interface {
// _FirmataMessage is the data-structure of this message
type _FirmataMessage struct {
- _SubType FirmataMessage
+ _SubType interface {
+ FirmataMessageContract
+ FirmataMessageRequirements
+ }
// Arguments.
Response bool
diff --git a/plc4go/protocols/firmata/readwrite/model/SysexCommand.go b/plc4go/protocols/firmata/readwrite/model/SysexCommand.go
index bb44f5d795c..6bcdb063baf 100644
--- a/plc4go/protocols/firmata/readwrite/model/SysexCommand.go
+++ b/plc4go/protocols/firmata/readwrite/model/SysexCommand.go
@@ -67,7 +67,10 @@ type SysexCommandRequirements interface {
// _SysexCommand is the data-structure of this message
type _SysexCommand struct {
- _SubType SysexCommand
+ _SubType interface {
+ SysexCommandContract
+ SysexCommandRequirements
+ }
}
var _ SysexCommandContract = (*_SysexCommand)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/Apdu.go b/plc4go/protocols/knxnetip/readwrite/model/Apdu.go
index e451e0ff7b6..d5e4e860509 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/Apdu.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/Apdu.go
@@ -71,7 +71,10 @@ type ApduRequirements interface {
// _Apdu is the data-structure of this message
type _Apdu struct {
- _SubType Apdu
+ _SubType interface {
+ ApduContract
+ ApduRequirements
+ }
Numbered bool
Counter uint8
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ApduControl.go b/plc4go/protocols/knxnetip/readwrite/model/ApduControl.go
index d7ea126a5f5..41cfdd99e34 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ApduControl.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ApduControl.go
@@ -65,7 +65,10 @@ type ApduControlRequirements interface {
// _ApduControl is the data-structure of this message
type _ApduControl struct {
- _SubType ApduControl
+ _SubType interface {
+ ApduControlContract
+ ApduControlRequirements
+ }
}
var _ ApduControlContract = (*_ApduControl)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ApduData.go b/plc4go/protocols/knxnetip/readwrite/model/ApduData.go
index ae24aff7f79..07cbe76560d 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ApduData.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ApduData.go
@@ -67,7 +67,10 @@ type ApduDataRequirements interface {
// _ApduData is the data-structure of this message
type _ApduData struct {
- _SubType ApduData
+ _SubType interface {
+ ApduDataContract
+ ApduDataRequirements
+ }
// Arguments.
DataLength uint8
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ApduDataExt.go b/plc4go/protocols/knxnetip/readwrite/model/ApduDataExt.go
index 4e98a3f0c3f..b2f25dcd016 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ApduDataExt.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ApduDataExt.go
@@ -67,7 +67,10 @@ type ApduDataExtRequirements interface {
// _ApduDataExt is the data-structure of this message
type _ApduDataExt struct {
- _SubType ApduDataExt
+ _SubType interface {
+ ApduDataExtContract
+ ApduDataExtRequirements
+ }
// Arguments.
Length uint8
diff --git a/plc4go/protocols/knxnetip/readwrite/model/CEMI.go b/plc4go/protocols/knxnetip/readwrite/model/CEMI.go
index 3f450931967..367960e7227 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/CEMI.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/CEMI.go
@@ -67,7 +67,10 @@ type CEMIRequirements interface {
// _CEMI is the data-structure of this message
type _CEMI struct {
- _SubType CEMI
+ _SubType interface {
+ CEMIContract
+ CEMIRequirements
+ }
// Arguments.
Size uint16
diff --git a/plc4go/protocols/knxnetip/readwrite/model/CEMIAdditionalInformation.go b/plc4go/protocols/knxnetip/readwrite/model/CEMIAdditionalInformation.go
index 1edf442c5fd..d2aaa985c43 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/CEMIAdditionalInformation.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/CEMIAdditionalInformation.go
@@ -65,7 +65,10 @@ type CEMIAdditionalInformationRequirements interface {
// _CEMIAdditionalInformation is the data-structure of this message
type _CEMIAdditionalInformation struct {
- _SubType CEMIAdditionalInformation
+ _SubType interface {
+ CEMIAdditionalInformationContract
+ CEMIAdditionalInformationRequirements
+ }
}
var _ CEMIAdditionalInformationContract = (*_CEMIAdditionalInformation)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ComObjectTable.go b/plc4go/protocols/knxnetip/readwrite/model/ComObjectTable.go
index 063aa2624da..d92747f7ba9 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ComObjectTable.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ComObjectTable.go
@@ -63,7 +63,10 @@ type ComObjectTableRequirements interface {
// _ComObjectTable is the data-structure of this message
type _ComObjectTable struct {
- _SubType ComObjectTable
+ _SubType interface {
+ ComObjectTableContract
+ ComObjectTableRequirements
+ }
}
var _ ComObjectTableContract = (*_ComObjectTable)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ConnectionRequestInformation.go b/plc4go/protocols/knxnetip/readwrite/model/ConnectionRequestInformation.go
index fa1bc0a6240..4e61b564b9e 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ConnectionRequestInformation.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ConnectionRequestInformation.go
@@ -65,7 +65,10 @@ type ConnectionRequestInformationRequirements interface {
// _ConnectionRequestInformation is the data-structure of this message
type _ConnectionRequestInformation struct {
- _SubType ConnectionRequestInformation
+ _SubType interface {
+ ConnectionRequestInformationContract
+ ConnectionRequestInformationRequirements
+ }
}
var _ ConnectionRequestInformationContract = (*_ConnectionRequestInformation)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ConnectionResponseDataBlock.go b/plc4go/protocols/knxnetip/readwrite/model/ConnectionResponseDataBlock.go
index 45e5b936200..f580dbcedc1 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ConnectionResponseDataBlock.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ConnectionResponseDataBlock.go
@@ -65,7 +65,10 @@ type ConnectionResponseDataBlockRequirements interface {
// _ConnectionResponseDataBlock is the data-structure of this message
type _ConnectionResponseDataBlock struct {
- _SubType ConnectionResponseDataBlock
+ _SubType interface {
+ ConnectionResponseDataBlockContract
+ ConnectionResponseDataBlockRequirements
+ }
}
var _ ConnectionResponseDataBlockContract = (*_ConnectionResponseDataBlock)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/KnxGroupAddress.go b/plc4go/protocols/knxnetip/readwrite/model/KnxGroupAddress.go
index 6c1f79998f3..93fc916550f 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/KnxGroupAddress.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/KnxGroupAddress.go
@@ -63,7 +63,10 @@ type KnxGroupAddressRequirements interface {
// _KnxGroupAddress is the data-structure of this message
type _KnxGroupAddress struct {
- _SubType KnxGroupAddress
+ _SubType interface {
+ KnxGroupAddressContract
+ KnxGroupAddressRequirements
+ }
}
var _ KnxGroupAddressContract = (*_KnxGroupAddress)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go b/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go
index e7e0e82b443..92fa8e6aad3 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/KnxManufacturer.go
@@ -734,8 +734,9 @@ const (
KnxManufacturer_M_ITALIANA_CONDUTTORI_SRL KnxManufacturer = 688
KnxManufacturer_M_XIAMEN_LEELEN_TECHNOLOGY_CO__LTD_ KnxManufacturer = 689
KnxManufacturer_M_LEDNX KnxManufacturer = 690
- KnxManufacturer_M_ABB___RESERVED KnxManufacturer = 691
- KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED KnxManufacturer = 692
+ KnxManufacturer_M_EBELONG KnxManufacturer = 691
+ KnxManufacturer_M_ABB___RESERVED KnxManufacturer = 692
+ KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED KnxManufacturer = 693
)
var KnxManufacturerValues []KnxManufacturer
@@ -1434,6 +1435,7 @@ func init() {
KnxManufacturer_M_ITALIANA_CONDUTTORI_SRL,
KnxManufacturer_M_XIAMEN_LEELEN_TECHNOLOGY_CO__LTD_,
KnxManufacturer_M_LEDNX,
+ KnxManufacturer_M_EBELONG,
KnxManufacturer_M_ABB___RESERVED,
KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED,
}
@@ -4075,10 +4077,14 @@ func (e KnxManufacturer) Number() uint16 {
}
case 691:
{ /* '691' */
- return 43954
+ return 749
}
case 692:
{ /* '692' */
+ return 43954
+ }
+ case 693:
+ { /* '693' */
return 43959
}
case 7:
@@ -6865,10 +6871,14 @@ func (e KnxManufacturer) Name() string {
}
case 691:
{ /* '691' */
- return "ABB - reserved"
+ return "ebelong"
}
case 692:
{ /* '692' */
+ return "ABB - reserved"
+ }
+ case 693:
+ { /* '693' */
return "Busch-Jaeger Elektro - reserved"
}
case 7:
@@ -8337,8 +8347,10 @@ func KnxManufacturerByValue(value uint16) (enum KnxManufacturer, ok bool) {
case 690:
return KnxManufacturer_M_LEDNX, true
case 691:
- return KnxManufacturer_M_ABB___RESERVED, true
+ return KnxManufacturer_M_EBELONG, true
case 692:
+ return KnxManufacturer_M_ABB___RESERVED, true
+ case 693:
return KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED, true
case 7:
return KnxManufacturer_M_GIRA_GIERSIEPEN, true
@@ -9728,6 +9740,8 @@ func KnxManufacturerByName(value string) (enum KnxManufacturer, ok bool) {
return KnxManufacturer_M_EELECTRON, true
case "M_LEDNX":
return KnxManufacturer_M_LEDNX, true
+ case "M_EBELONG":
+ return KnxManufacturer_M_EBELONG, true
case "M_ABB___RESERVED":
return KnxManufacturer_M_ABB___RESERVED, true
case "M_BUSCH_JAEGER_ELEKTRO___RESERVED":
@@ -11192,6 +11206,8 @@ func (e KnxManufacturer) PLC4XEnumName() string {
return "M_EELECTRON"
case KnxManufacturer_M_LEDNX:
return "M_LEDNX"
+ case KnxManufacturer_M_EBELONG:
+ return "M_EBELONG"
case KnxManufacturer_M_ABB___RESERVED:
return "M_ABB___RESERVED"
case KnxManufacturer_M_BUSCH_JAEGER_ELEKTRO___RESERVED:
diff --git a/plc4go/protocols/knxnetip/readwrite/model/KnxNetIpMessage.go b/plc4go/protocols/knxnetip/readwrite/model/KnxNetIpMessage.go
index da6c595f595..43bdcf1a0cc 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/KnxNetIpMessage.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/KnxNetIpMessage.go
@@ -70,7 +70,10 @@ type KnxNetIpMessageRequirements interface {
// _KnxNetIpMessage is the data-structure of this message
type _KnxNetIpMessage struct {
- _SubType KnxNetIpMessage
+ _SubType interface {
+ KnxNetIpMessageContract
+ KnxNetIpMessageRequirements
+ }
}
var _ KnxNetIpMessageContract = (*_KnxNetIpMessage)(nil)
diff --git a/plc4go/protocols/knxnetip/readwrite/model/LDataFrame.go b/plc4go/protocols/knxnetip/readwrite/model/LDataFrame.go
index 0a13164ce40..d41d7fb339a 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/LDataFrame.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/LDataFrame.go
@@ -77,7 +77,10 @@ type LDataFrameRequirements interface {
// _LDataFrame is the data-structure of this message
type _LDataFrame struct {
- _SubType LDataFrame
+ _SubType interface {
+ LDataFrameContract
+ LDataFrameRequirements
+ }
FrameType bool
NotRepeated bool
Priority CEMIPriority
diff --git a/plc4go/protocols/knxnetip/readwrite/model/ServiceId.go b/plc4go/protocols/knxnetip/readwrite/model/ServiceId.go
index e0b8f289d3f..ce1f2ec81c2 100644
--- a/plc4go/protocols/knxnetip/readwrite/model/ServiceId.go
+++ b/plc4go/protocols/knxnetip/readwrite/model/ServiceId.go
@@ -65,7 +65,10 @@ type ServiceIdRequirements interface {
// _ServiceId is the data-structure of this message
type _ServiceId struct {
- _SubType ServiceId
+ _SubType interface {
+ ServiceIdContract
+ ServiceIdRequirements
+ }
}
var _ ServiceIdContract = (*_ServiceId)(nil)
diff --git a/plc4go/protocols/modbus/readwrite/model/ModbusADU.go b/plc4go/protocols/modbus/readwrite/model/ModbusADU.go
index c8033eac511..2d6b25f56a2 100644
--- a/plc4go/protocols/modbus/readwrite/model/ModbusADU.go
+++ b/plc4go/protocols/modbus/readwrite/model/ModbusADU.go
@@ -66,7 +66,10 @@ type ModbusADURequirements interface {
// _ModbusADU is the data-structure of this message
type _ModbusADU struct {
- _SubType ModbusADU
+ _SubType interface {
+ ModbusADUContract
+ ModbusADURequirements
+ }
// Arguments.
Response bool
diff --git a/plc4go/protocols/modbus/readwrite/model/ModbusPDU.go b/plc4go/protocols/modbus/readwrite/model/ModbusPDU.go
index 11393507eea..d8840ce5774 100644
--- a/plc4go/protocols/modbus/readwrite/model/ModbusPDU.go
+++ b/plc4go/protocols/modbus/readwrite/model/ModbusPDU.go
@@ -69,7 +69,10 @@ type ModbusPDURequirements interface {
// _ModbusPDU is the data-structure of this message
type _ModbusPDU struct {
- _SubType ModbusPDU
+ _SubType interface {
+ ModbusPDUContract
+ ModbusPDURequirements
+ }
}
var _ ModbusPDUContract = (*_ModbusPDU)(nil)
diff --git a/plc4go/protocols/opcua/readwrite/model/ExtensionObjectDefinition.go b/plc4go/protocols/opcua/readwrite/model/ExtensionObjectDefinition.go
index 74363c25dd4..42fd29c639e 100644
--- a/plc4go/protocols/opcua/readwrite/model/ExtensionObjectDefinition.go
+++ b/plc4go/protocols/opcua/readwrite/model/ExtensionObjectDefinition.go
@@ -63,7 +63,10 @@ type ExtensionObjectDefinitionRequirements interface {
// _ExtensionObjectDefinition is the data-structure of this message
type _ExtensionObjectDefinition struct {
- _SubType ExtensionObjectDefinition
+ _SubType interface {
+ ExtensionObjectDefinitionContract
+ ExtensionObjectDefinitionRequirements
+ }
}
var _ ExtensionObjectDefinitionContract = (*_ExtensionObjectDefinition)(nil)
diff --git a/plc4go/protocols/opcua/readwrite/model/MessagePDU.go b/plc4go/protocols/opcua/readwrite/model/MessagePDU.go
index 429f4e097b2..b3ca4aad8e7 100644
--- a/plc4go/protocols/opcua/readwrite/model/MessagePDU.go
+++ b/plc4go/protocols/opcua/readwrite/model/MessagePDU.go
@@ -69,8 +69,11 @@ type MessagePDURequirements interface {
// _MessagePDU is the data-structure of this message
type _MessagePDU struct {
- _SubType MessagePDU
- Chunk ChunkType
+ _SubType interface {
+ MessagePDUContract
+ MessagePDURequirements
+ }
+ Chunk ChunkType
}
var _ MessagePDUContract = (*_MessagePDU)(nil)
diff --git a/plc4go/protocols/opcua/readwrite/model/NodeIdTypeDefinition.go b/plc4go/protocols/opcua/readwrite/model/NodeIdTypeDefinition.go
index 8b81409aaec..8958237c501 100644
--- a/plc4go/protocols/opcua/readwrite/model/NodeIdTypeDefinition.go
+++ b/plc4go/protocols/opcua/readwrite/model/NodeIdTypeDefinition.go
@@ -69,7 +69,10 @@ type NodeIdTypeDefinitionRequirements interface {
// _NodeIdTypeDefinition is the data-structure of this message
type _NodeIdTypeDefinition struct {
- _SubType NodeIdTypeDefinition
+ _SubType interface {
+ NodeIdTypeDefinitionContract
+ NodeIdTypeDefinitionRequirements
+ }
}
var _ NodeIdTypeDefinitionContract = (*_NodeIdTypeDefinition)(nil)
diff --git a/plc4go/protocols/opcua/readwrite/model/OpenChannelMessage.go b/plc4go/protocols/opcua/readwrite/model/OpenChannelMessage.go
index 31bfcc871ee..faf89033f9c 100644
--- a/plc4go/protocols/opcua/readwrite/model/OpenChannelMessage.go
+++ b/plc4go/protocols/opcua/readwrite/model/OpenChannelMessage.go
@@ -63,7 +63,10 @@ type OpenChannelMessageRequirements interface {
// _OpenChannelMessage is the data-structure of this message
type _OpenChannelMessage struct {
- _SubType OpenChannelMessage
+ _SubType interface {
+ OpenChannelMessageContract
+ OpenChannelMessageRequirements
+ }
}
var _ OpenChannelMessageContract = (*_OpenChannelMessage)(nil)
diff --git a/plc4go/protocols/opcua/readwrite/model/Payload.go b/plc4go/protocols/opcua/readwrite/model/Payload.go
index 7fa072452f5..e7380124826 100644
--- a/plc4go/protocols/opcua/readwrite/model/Payload.go
+++ b/plc4go/protocols/opcua/readwrite/model/Payload.go
@@ -69,7 +69,10 @@ type PayloadRequirements interface {
// _Payload is the data-structure of this message
type _Payload struct {
- _SubType Payload
+ _SubType interface {
+ PayloadContract
+ PayloadRequirements
+ }
SequenceHeader SequenceHeader
// Arguments.
diff --git a/plc4go/protocols/opcua/readwrite/model/UserIdentityTokenDefinition.go b/plc4go/protocols/opcua/readwrite/model/UserIdentityTokenDefinition.go
index b08290150bd..112c5125254 100644
--- a/plc4go/protocols/opcua/readwrite/model/UserIdentityTokenDefinition.go
+++ b/plc4go/protocols/opcua/readwrite/model/UserIdentityTokenDefinition.go
@@ -63,7 +63,10 @@ type UserIdentityTokenDefinitionRequirements interface {
// _UserIdentityTokenDefinition is the data-structure of this message
type _UserIdentityTokenDefinition struct {
- _SubType UserIdentityTokenDefinition
+ _SubType interface {
+ UserIdentityTokenDefinitionContract
+ UserIdentityTokenDefinitionRequirements
+ }
}
var _ UserIdentityTokenDefinitionContract = (*_UserIdentityTokenDefinition)(nil)
diff --git a/plc4go/protocols/opcua/readwrite/model/Variant.go b/plc4go/protocols/opcua/readwrite/model/Variant.go
index 19bab5f54a8..0efb24d2c57 100644
--- a/plc4go/protocols/opcua/readwrite/model/Variant.go
+++ b/plc4go/protocols/opcua/readwrite/model/Variant.go
@@ -75,7 +75,10 @@ type VariantRequirements interface {
// _Variant is the data-structure of this message
type _Variant struct {
- _SubType Variant
+ _SubType interface {
+ VariantContract
+ VariantRequirements
+ }
ArrayLengthSpecified bool
ArrayDimensionsSpecified bool
NoOfArrayDimensions *int32
diff --git a/plc4go/protocols/s7/readwrite/model/COTPPacket.go b/plc4go/protocols/s7/readwrite/model/COTPPacket.go
index 636232487be..84c06f27d42 100644
--- a/plc4go/protocols/s7/readwrite/model/COTPPacket.go
+++ b/plc4go/protocols/s7/readwrite/model/COTPPacket.go
@@ -71,7 +71,10 @@ type COTPPacketRequirements interface {
// _COTPPacket is the data-structure of this message
type _COTPPacket struct {
- _SubType COTPPacket
+ _SubType interface {
+ COTPPacketContract
+ COTPPacketRequirements
+ }
Parameters []COTPParameter
Payload S7Message
diff --git a/plc4go/protocols/s7/readwrite/model/COTPParameter.go b/plc4go/protocols/s7/readwrite/model/COTPParameter.go
index d2a386366f6..cb2986d34ce 100644
--- a/plc4go/protocols/s7/readwrite/model/COTPParameter.go
+++ b/plc4go/protocols/s7/readwrite/model/COTPParameter.go
@@ -67,7 +67,10 @@ type COTPParameterRequirements interface {
// _COTPParameter is the data-structure of this message
type _COTPParameter struct {
- _SubType COTPParameter
+ _SubType interface {
+ COTPParameterContract
+ COTPParameterRequirements
+ }
// Arguments.
Rest uint8
diff --git a/plc4go/protocols/s7/readwrite/model/CycServiceItemType.go b/plc4go/protocols/s7/readwrite/model/CycServiceItemType.go
index d4a6583f65d..dc1328301e9 100644
--- a/plc4go/protocols/s7/readwrite/model/CycServiceItemType.go
+++ b/plc4go/protocols/s7/readwrite/model/CycServiceItemType.go
@@ -72,7 +72,10 @@ type CycServiceItemTypeRequirements interface {
// _CycServiceItemType is the data-structure of this message
type _CycServiceItemType struct {
- _SubType CycServiceItemType
+ _SubType interface {
+ CycServiceItemTypeContract
+ CycServiceItemTypeRequirements
+ }
ByteLength uint8
SyntaxId uint8
}
diff --git a/plc4go/protocols/s7/readwrite/model/S7Address.go b/plc4go/protocols/s7/readwrite/model/S7Address.go
index 7e651060f15..1b3073ffa94 100644
--- a/plc4go/protocols/s7/readwrite/model/S7Address.go
+++ b/plc4go/protocols/s7/readwrite/model/S7Address.go
@@ -65,7 +65,10 @@ type S7AddressRequirements interface {
// _S7Address is the data-structure of this message
type _S7Address struct {
- _SubType S7Address
+ _SubType interface {
+ S7AddressContract
+ S7AddressRequirements
+ }
}
var _ S7AddressContract = (*_S7Address)(nil)
diff --git a/plc4go/protocols/s7/readwrite/model/S7DataAlarmMessage.go b/plc4go/protocols/s7/readwrite/model/S7DataAlarmMessage.go
index eb532f2f50e..eed0881c7ce 100644
--- a/plc4go/protocols/s7/readwrite/model/S7DataAlarmMessage.go
+++ b/plc4go/protocols/s7/readwrite/model/S7DataAlarmMessage.go
@@ -69,7 +69,10 @@ type S7DataAlarmMessageRequirements interface {
// _S7DataAlarmMessage is the data-structure of this message
type _S7DataAlarmMessage struct {
- _SubType S7DataAlarmMessage
+ _SubType interface {
+ S7DataAlarmMessageContract
+ S7DataAlarmMessageRequirements
+ }
}
var _ S7DataAlarmMessageContract = (*_S7DataAlarmMessage)(nil)
diff --git a/plc4go/protocols/s7/readwrite/model/S7Message.go b/plc4go/protocols/s7/readwrite/model/S7Message.go
index 8b8d88a4a63..85ab659384a 100644
--- a/plc4go/protocols/s7/readwrite/model/S7Message.go
+++ b/plc4go/protocols/s7/readwrite/model/S7Message.go
@@ -74,7 +74,10 @@ type S7MessageRequirements interface {
// _S7Message is the data-structure of this message
type _S7Message struct {
- _SubType S7Message
+ _SubType interface {
+ S7MessageContract
+ S7MessageRequirements
+ }
TpduReference uint16
Parameter S7Parameter
Payload S7Payload
diff --git a/plc4go/protocols/s7/readwrite/model/S7Parameter.go b/plc4go/protocols/s7/readwrite/model/S7Parameter.go
index 2f7e06161be..fb26868d5ca 100644
--- a/plc4go/protocols/s7/readwrite/model/S7Parameter.go
+++ b/plc4go/protocols/s7/readwrite/model/S7Parameter.go
@@ -67,7 +67,10 @@ type S7ParameterRequirements interface {
// _S7Parameter is the data-structure of this message
type _S7Parameter struct {
- _SubType S7Parameter
+ _SubType interface {
+ S7ParameterContract
+ S7ParameterRequirements
+ }
}
var _ S7ParameterContract = (*_S7Parameter)(nil)
diff --git a/plc4go/protocols/s7/readwrite/model/S7ParameterUserDataItem.go b/plc4go/protocols/s7/readwrite/model/S7ParameterUserDataItem.go
index 9608b095d3b..c812ca31867 100644
--- a/plc4go/protocols/s7/readwrite/model/S7ParameterUserDataItem.go
+++ b/plc4go/protocols/s7/readwrite/model/S7ParameterUserDataItem.go
@@ -65,7 +65,10 @@ type S7ParameterUserDataItemRequirements interface {
// _S7ParameterUserDataItem is the data-structure of this message
type _S7ParameterUserDataItem struct {
- _SubType S7ParameterUserDataItem
+ _SubType interface {
+ S7ParameterUserDataItemContract
+ S7ParameterUserDataItemRequirements
+ }
}
var _ S7ParameterUserDataItemContract = (*_S7ParameterUserDataItem)(nil)
diff --git a/plc4go/protocols/s7/readwrite/model/S7Payload.go b/plc4go/protocols/s7/readwrite/model/S7Payload.go
index a54e7038eff..bfb79e6eaa1 100644
--- a/plc4go/protocols/s7/readwrite/model/S7Payload.go
+++ b/plc4go/protocols/s7/readwrite/model/S7Payload.go
@@ -67,7 +67,10 @@ type S7PayloadRequirements interface {
// _S7Payload is the data-structure of this message
type _S7Payload struct {
- _SubType S7Payload
+ _SubType interface {
+ S7PayloadContract
+ S7PayloadRequirements
+ }
// Arguments.
Parameter S7Parameter
diff --git a/plc4go/protocols/s7/readwrite/model/S7PayloadUserDataItem.go b/plc4go/protocols/s7/readwrite/model/S7PayloadUserDataItem.go
index 4e626a2a938..d2b56fabe7d 100644
--- a/plc4go/protocols/s7/readwrite/model/S7PayloadUserDataItem.go
+++ b/plc4go/protocols/s7/readwrite/model/S7PayloadUserDataItem.go
@@ -77,7 +77,10 @@ type S7PayloadUserDataItemRequirements interface {
// _S7PayloadUserDataItem is the data-structure of this message
type _S7PayloadUserDataItem struct {
- _SubType S7PayloadUserDataItem
+ _SubType interface {
+ S7PayloadUserDataItemContract
+ S7PayloadUserDataItemRequirements
+ }
ReturnCode DataTransportErrorCode
TransportSize DataTransportSize
DataLength uint16
diff --git a/plc4go/protocols/s7/readwrite/model/S7VarRequestParameterItem.go b/plc4go/protocols/s7/readwrite/model/S7VarRequestParameterItem.go
index 00a78bca6ac..0cc77c6e01d 100644
--- a/plc4go/protocols/s7/readwrite/model/S7VarRequestParameterItem.go
+++ b/plc4go/protocols/s7/readwrite/model/S7VarRequestParameterItem.go
@@ -65,7 +65,10 @@ type S7VarRequestParameterItemRequirements interface {
// _S7VarRequestParameterItem is the data-structure of this message
type _S7VarRequestParameterItem struct {
- _SubType S7VarRequestParameterItem
+ _SubType interface {
+ S7VarRequestParameterItemContract
+ S7VarRequestParameterItemRequirements
+ }
}
var _ S7VarRequestParameterItemContract = (*_S7VarRequestParameterItem)(nil)
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcMetadataKeys.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcMetadataKeys.java
new file mode 100644
index 00000000000..e88ca207f32
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcMetadataKeys.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.api.messages;
+
+import org.apache.plc4x.java.api.metadata.Metadata.Key;
+import org.apache.plc4x.java.api.metadata.time.TimeSource;
+
+/**
+ * High level definition of common metadata keys which can occur across multiple drivers.
+ */
+public interface PlcMetadataKeys {
+
+ Key TIMESTAMP = Key.of("timestamp", Long.class);
+ Key TIMESTAMP_SOURCE = Key.of("timestamp_source", TimeSource.class);
+
+ Key RECEIVE_TIMESTAMP = Key.of("receive_timestamp", Long.class);
+
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcTagResponse.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcTagResponse.java
index 3aa2d642deb..1feae9f3bbb 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcTagResponse.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcTagResponse.java
@@ -18,6 +18,7 @@
*/
package org.apache.plc4x.java.api.messages;
+import org.apache.plc4x.java.api.metadata.Metadata;
import org.apache.plc4x.java.api.model.PlcTag;
import org.apache.plc4x.java.api.types.PlcResponseCode;
@@ -38,4 +39,9 @@ public interface PlcTagResponse extends PlcResponse {
PlcResponseCode getResponseCode(String name);
+ /**
+ * Returns tag level metadata information.
+ */
+ Metadata getTagMetadata(String name);
+
}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/Metadata.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/Metadata.java
new file mode 100644
index 00000000000..484fad7148a
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/Metadata.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.api.metadata;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public interface Metadata {
+
+ Metadata EMPTY = new Metadata() {
+ @Override
+ public Set> keys() {
+ return Set.of();
+ }
+
+ @Override
+ public Map, Object> entries() {
+ return Map.of();
+ }
+
+ @Override
+ public Object getValue(Key> key) {
+ return null;
+ }
+
+ };
+
+ class Key {
+
+ private final String key;
+ private final Class type;
+
+ protected Key(String key, Class type) {
+ this.key = key;
+ this.type = type;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public boolean validate(Object value) {
+ return type.isInstance(value);
+ }
+
+ public static Key of(String key, Class type) {
+ return new Key<>(key, type);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Key)) {
+ return false;
+ }
+ Key> key1 = (Key>) o;
+ return Objects.equals(getKey(), key1.getKey()) && Objects.equals(type, key1.type);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getKey(), type);
+ }
+ }
+
+ Set> keys();
+ Map, Object> entries();
+ Object getValue(Key> key);
+}
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/time/TimeSource.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/time/TimeSource.java
new file mode 100644
index 00000000000..84e5843635d
--- /dev/null
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/metadata/time/TimeSource.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.api.metadata.time;
+
+public enum TimeSource {
+
+ // Time information is assumed by PLC4X itself
+ ASSUMPTION,
+ // Time comes from software layer, kernel driver and similar
+ SOFTWARE,
+ // Time can is confronted through hardware i.e. microcontroller
+ HARDWARE,
+ // Other source of time which fall into separate truthiness category
+ OTHER
+
+}
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index 08eaa141d06..7a58931ae7e 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -34,6 +34,9 @@
import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.metadata.Metadata;
+import org.apache.plc4x.java.spi.metadata.DefaultMetadata;
+import org.apache.plc4x.java.api.metadata.time.TimeSource;
import org.apache.plc4x.java.api.model.*;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.api.types.PlcSubscriptionType;
@@ -718,8 +721,13 @@ protected CompletableFuture singleRead(PlcReadRequest readReque
.check(userdata -> userdata.getInvokeId() == amsPacket.getInvokeId())
.only(AdsReadResponse.class)
.handle(response -> {
+ // result metadata
+ Metadata metadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, System.currentTimeMillis())
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build();
if (response.getResult() == ReturnCode.OK) {
- final PlcReadResponse plcReadResponse = convertToPlc4xReadResponse(readRequest, Map.of((AdsTag) readRequest.getTags().get(0), directAdsTag), response);
+ final PlcReadResponse plcReadResponse = convertToPlc4xReadResponse(readRequest, Map.of((AdsTag) readRequest.getTags().get(0), directAdsTag), response, metadata);
// Convert the response from the PLC into a PLC4X Response ...
future.complete(plcReadResponse);
} else {
@@ -791,8 +799,12 @@ protected CompletableFuture multiRead(PlcReadRequest readReques
.check(userdata -> userdata.getInvokeId() == amsPacket.getInvokeId())
.only(AdsReadWriteResponse.class)
.handle(response -> {
+ Metadata metadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, System.currentTimeMillis())
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build();
if (response.getResult() == ReturnCode.OK) {
- final PlcReadResponse plcReadResponse = convertToPlc4xReadResponse(readRequest, resolvedTags, response);
+ final PlcReadResponse plcReadResponse = convertToPlc4xReadResponse(readRequest, resolvedTags, response, metadata);
// Convert the response from the PLC into a PLC4X Response ...
future.complete(plcReadResponse);
} else if (response.getResult() == ReturnCode.ADSERR_DEVICE_INVALIDSIZE) {
@@ -807,8 +819,9 @@ protected CompletableFuture multiRead(PlcReadRequest readReques
return future;
}
- protected PlcReadResponse convertToPlc4xReadResponse(PlcReadRequest readRequest, Map resolvedTags, AmsPacket adsData) {
+ protected PlcReadResponse convertToPlc4xReadResponse(PlcReadRequest readRequest, Map resolvedTags, AmsPacket adsData, Metadata responseMetadata) {
ReadBuffer readBuffer = null;
+ Map metadata = new HashMap<>();
Map responseCodes = new HashMap<>();
// Read the response codes first
@@ -841,6 +854,7 @@ protected PlcReadResponse convertToPlc4xReadResponse(PlcReadRequest readRequest,
if (readBuffer != null) {
Map> values = new HashMap<>();
for (String tagName : readRequest.getTagNames()) {
+ metadata.put(tagName, new DefaultMetadata.Builder(responseMetadata).build());
// If the response-code was anything but OK, we don't need to parse the payload.
if(responseCodes.get(tagName) != PlcResponseCode.OK) {
values.put(tagName, new DefaultPlcResponseItem<>(responseCodes.get(tagName), null));
@@ -851,7 +865,7 @@ protected PlcReadResponse convertToPlc4xReadResponse(PlcReadRequest readRequest,
values.put(tagName, parseResponseItem(directAdsTag, readBuffer));
}
}
- return new DefaultPlcReadResponse(readRequest, values);
+ return new DefaultPlcReadResponse(readRequest, values, metadata);
}
return null;
}
@@ -1071,8 +1085,13 @@ protected CompletableFuture singleWrite(PlcWriteRequest writeR
.check(userdata -> userdata.getInvokeId() == amsPacket.getInvokeId())
.only(AdsWriteResponse.class)
.handle(response -> {
+ // result metadata
+ Metadata eventMetadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, System.currentTimeMillis())
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build();
if (response.getResult() == ReturnCode.OK) {
- final PlcWriteResponse plcWriteResponse = convertToPlc4xWriteResponse(writeRequest, Collections.singletonMap((AdsTag) writeRequest.getTag(tagName), directAdsTag), response);
+ final PlcWriteResponse plcWriteResponse = convertToPlc4xWriteResponse(writeRequest, Collections.singletonMap((AdsTag) writeRequest.getTag(tagName), directAdsTag), response, eventMetadata);
// Convert the response from the PLC into a PLC4X Response ...
future.complete(plcWriteResponse);
} else {
@@ -1149,8 +1168,14 @@ protected CompletableFuture multiWrite(PlcWriteRequest writeRe
.check(userdata -> userdata.getInvokeId() == amsPacket.getInvokeId())
.only(AdsReadWriteResponse.class)
.handle(response -> {
+ // result metadata
+ Metadata eventMetadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, System.currentTimeMillis())
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build();
+
if (response.getResult() == ReturnCode.OK) {
- final PlcWriteResponse plcWriteResponse = convertToPlc4xWriteResponse(writeRequest, resolvedTags, response);
+ final PlcWriteResponse plcWriteResponse = convertToPlc4xWriteResponse(writeRequest, resolvedTags, response, eventMetadata);
// Convert the response from the PLC into a PLC4X Response ...
future.complete(plcWriteResponse);
} else {
@@ -1244,8 +1269,9 @@ else if (!dataType.getChildren().isEmpty()) {
}
}
- protected PlcWriteResponse convertToPlc4xWriteResponse(PlcWriteRequest writeRequest, Map resolvedTags, AmsPacket adsData) {
+ protected PlcWriteResponse convertToPlc4xWriteResponse(PlcWriteRequest writeRequest, Map resolvedTags, AmsPacket adsData, Metadata eventMtadata) {
Map responseCodes = new HashMap<>();
+ Map metadata = new HashMap<>();
if (adsData instanceof AdsWriteResponse) {
AdsWriteResponse adsWriteResponse = (AdsWriteResponse) adsData;
responseCodes.put(writeRequest.getTagNames().stream().findFirst().orElse(""),
@@ -1256,6 +1282,9 @@ protected PlcWriteResponse convertToPlc4xWriteResponse(PlcWriteRequest writeRequ
// When parsing a multi-item response, the error codes of each items come
// in sequence and then come the values.
for (String tagName : writeRequest.getTagNames()) {
+ // result metadata
+ metadata.put(tagName, eventMtadata);
+
AdsTag adsTag = (AdsTag) writeRequest.getTag(tagName);
// Skip invalid addresses.
if(resolvedTags.get(adsTag) == null) {
@@ -1271,7 +1300,7 @@ protected PlcWriteResponse convertToPlc4xWriteResponse(PlcWriteRequest writeRequ
}
}
- return new DefaultPlcWriteResponse(writeRequest, responseCodes);
+ return new DefaultPlcWriteResponse(writeRequest, responseCodes, metadata);
}
@Override
@@ -1493,9 +1522,16 @@ protected void decode(ConversationContext context, AmsTCPPacket ms
if (msg.getUserdata() instanceof AdsDeviceNotificationRequest) {
AdsDeviceNotificationRequest notificationData = (AdsDeviceNotificationRequest) msg.getUserdata();
List stamps = notificationData.getAdsStampHeaders();
+ long receiveTs = System.currentTimeMillis();
for (AdsStampHeader stamp : stamps) {
// convert Windows FILETIME format to unix epoch
long unixEpochTimestamp = stamp.getTimestamp().divide(BigInteger.valueOf(10000L)).longValue() - 11644473600000L;
+ // result metadata
+ Metadata eventMetadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, receiveTs)
+ .put(PlcMetadataKeys.TIMESTAMP, unixEpochTimestamp)
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.SOFTWARE)
+ .build();
List samples = stamp.getAdsNotificationSamples();
for (AdsNotificationSample sample : samples) {
long handle = sample.getNotificationHandle();
@@ -1503,10 +1539,12 @@ protected void decode(ConversationContext context, AmsTCPPacket ms
for (PlcSubscriptionHandle subscriptionHandle : registration.getSubscriptionHandles()) {
if (subscriptionHandle instanceof AdsSubscriptionHandle) {
AdsSubscriptionHandle adsHandle = (AdsSubscriptionHandle) subscriptionHandle;
- if (adsHandle.getNotificationHandle() == handle)
- consumers.get(registration).accept(
- new DefaultPlcSubscriptionEvent(Instant.ofEpochMilli(unixEpochTimestamp),
- convertSampleToPlc4XResult(adsHandle, sample.getData())));
+ if (adsHandle.getNotificationHandle() == handle) {
+ Map metadata = new HashMap<>();
+ Instant timestamp = Instant.ofEpochMilli(unixEpochTimestamp);
+ DefaultPlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent(timestamp, convertSampleToPlc4XResult(adsHandle, sample.getData(), metadata, eventMetadata));
+ consumers.get(registration).accept(event);
+ }
}
}
}
@@ -1515,12 +1553,13 @@ protected void decode(ConversationContext context, AmsTCPPacket ms
}
}
- private Map> convertSampleToPlc4XResult(AdsSubscriptionHandle subscriptionHandle, byte[] data) throws
+ private Map> convertSampleToPlc4XResult(AdsSubscriptionHandle subscriptionHandle, byte[] data, Map tagMetadata, Metadata metadata) throws
ParseException {
Map> values = new HashMap<>();
ReadBufferByteBased readBuffer = new ReadBufferByteBased(data, ByteOrder.LITTLE_ENDIAN);
values.put(subscriptionHandle.getTagName(), new DefaultPlcResponseItem<>(PlcResponseCode.OK,
DataItem.staticParse(readBuffer, getPlcValueTypeForAdsDataType(subscriptionHandle.getAdsDataType()), data.length)));
+ tagMetadata.put(subscriptionHandle.getTagName(), new DefaultMetadata.Builder(metadata).build());
return values;
}
diff --git a/plc4j/drivers/ctrlx/pom.xml b/plc4j/drivers/ctrlx/pom.xml
index f3cfc64e70e..5e4b7af9cb4 100644
--- a/plc4j/drivers/ctrlx/pom.xml
+++ b/plc4j/drivers/ctrlx/pom.xml
@@ -187,7 +187,7 @@
org.jetbrains.kotlinkotlin-stdlib-jdk8
- 2.0.20
+ 2.0.21
diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml
index fe4f92536b9..c63e139f1bf 100644
--- a/plc4j/drivers/opcua/pom.xml
+++ b/plc4j/drivers/opcua/pom.xml
@@ -212,7 +212,7 @@
org.testcontainerstestcontainers
- 1.20.2
+ 1.20.3test
@@ -224,7 +224,7 @@
com.google.cloud.toolsjib-core
- 0.27.1
+ 0.27.2test
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcMetadataKeys.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcMetadataKeys.java
new file mode 100644
index 00000000000..713081159ca
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcMetadataKeys.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.opcua;
+
+import org.apache.plc4x.java.api.metadata.Metadata;
+import org.apache.plc4x.java.api.metadata.Metadata.Key;
+import org.apache.plc4x.java.opcua.tag.OpcuaQualityStatus;
+
+/**
+ * OPC UA level metadata keys.
+ */
+public interface OpcMetadataKeys {
+
+ Key QUALITY = Metadata.Key.of("opcua_quality", OpcuaQualityStatus.class);
+
+ Key SERVER_TIMESTAMP = Metadata.Key.of("opcua_server_timestamp", Long.class);
+ Key SOURCE_TIMESTAMP = Metadata.Key.of("opcua_source_timestamp", Long.class);
+
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
index 91112aef604..0ccf130a5b3 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
@@ -26,18 +26,23 @@
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.metadata.Metadata;
+import org.apache.plc4x.java.spi.metadata.DefaultMetadata;
+import org.apache.plc4x.java.api.metadata.time.TimeSource;
import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
import org.apache.plc4x.java.api.model.PlcSubscriptionHandle;
import org.apache.plc4x.java.api.model.PlcTag;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.api.types.PlcValueType;
import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.opcua.OpcMetadataKeys;
import org.apache.plc4x.java.opcua.config.OpcuaConfiguration;
import org.apache.plc4x.java.opcua.context.Conversation;
import org.apache.plc4x.java.opcua.context.OpcuaDriverContext;
import org.apache.plc4x.java.opcua.context.SecureChannel;
import org.apache.plc4x.java.opcua.readwrite.*;
import org.apache.plc4x.java.opcua.tag.OpcuaPlcTagHandler;
+import org.apache.plc4x.java.opcua.tag.OpcuaQualityStatus;
import org.apache.plc4x.java.opcua.tag.OpcuaTag;
import org.apache.plc4x.java.spi.ConversationContext;
import org.apache.plc4x.java.spi.Plc4xProtocolBase;
@@ -210,7 +215,7 @@ public CompletableFuture read(PlcReadRequest readRequest) {
List readValueArray = new ArrayList<>(request.getTagNames().size());
Iterator iterator = request.getTagNames().iterator();
- Map tagMap = new HashMap<>();
+ Map tagMap = new LinkedHashMap<>();
for (int i = 0; i < request.getTagNames().size(); i++) {
String tagName = iterator.next();
// TODO: We need to check that the tag-return-code is OK as it could also be INVALID_TAG
@@ -237,7 +242,13 @@ public CompletableFuture read(PlcReadRequest readRequest) {
transaction.submit(() -> {
conversation.submit(opcuaReadRequest, ReadResponse.class).whenComplete((response, error) -> bridge(transaction, future, response, error));
});
- return future.thenApply(response -> new DefaultPlcReadResponse(request, readResponse(request.getTagNames(), tagMap, response.getResults())));
+ return future.thenApply(response -> {
+ Metadata responseMetadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, System.currentTimeMillis())
+ .build();
+ Map metadata = new LinkedHashMap<>();
+ return new DefaultPlcReadResponse(request, readResponse(tagMap, response.getResults(), metadata, responseMetadata), metadata);
+ });
}
static NodeId generateNodeId(OpcuaTag tag) {
@@ -262,15 +273,16 @@ static NodeId generateNodeId(OpcuaTag tag) {
return nodeId;
}
- public Map> readResponse(LinkedHashSet tagNames, Map tagMap, List results) {
+ public Map> readResponse(Map tagMap, List results, Map metadata, Metadata responseMetadata) {
PlcResponseCode responseCode = null; // initialize variable
Map> response = new HashMap<>();
- int count = 0;
- for (String tagName : tagNames) {
+ int index = 0;
+ for (String tagName : tagMap.keySet()) {
PlcTag tag = tagMap.get(tagName);
PlcValue value = null;
- if (results.get(count).getValueSpecified()) {
- Variant variant = results.get(count).getValue();
+ DataValue dataValue = results.get(index++);
+ if (dataValue.getValueSpecified()) {
+ Variant variant = dataValue.getValue();
LOGGER.trace("Response of type {}", variant.getClass().toString());
if (variant instanceof VariantBoolean) {
byte[] array = ((VariantBoolean) variant).getValue();
@@ -423,12 +435,20 @@ public Map> readResponse(LinkedHashSet
responseCode = PlcResponseCode.OK;
}
} else {
- StatusCode statusCode = results.get(count).getStatusCode();
+ StatusCode statusCode = dataValue.getStatusCode();
responseCode = mapOpcStatusCode(statusCode.getStatusCode(), PlcResponseCode.UNSUPPORTED);
- LOGGER.error("Error while reading value from OPC UA server error code: {}", results.get(count).getStatusCode().toString());
+ LOGGER.error("Error while reading value from OPC UA server error code:- " + dataValue.getStatusCode().toString());
}
- count++;
+
+ Metadata tagMetadata = new DefaultMetadata.Builder(responseMetadata)
+ .put(OpcMetadataKeys.QUALITY, new OpcuaQualityStatus(dataValue.getStatusCode()))
+ .put(OpcMetadataKeys.SERVER_TIMESTAMP, dataValue.getServerTimestamp())
+ .put(OpcMetadataKeys.SOURCE_TIMESTAMP, dataValue.getSourceTimestamp())
+ .put(PlcMetadataKeys.TIMESTAMP, dataValue.getServerTimestamp())
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.SOFTWARE)
+ .build();
response.put(tagName, new DefaultPlcResponseItem<>(responseCode, value));
+ metadata.put(tagName, tagMetadata);
}
return response;
}
@@ -880,4 +900,5 @@ private static void bridge(RequestTransaction transaction, CompletableFuture
transaction.endRequest();
}
}
+
}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandle.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandle.java
index ab241b0411e..4889480f3cd 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandle.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandle.java
@@ -24,8 +24,11 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+import org.apache.plc4x.java.api.messages.PlcMetadataKeys;
import org.apache.plc4x.java.api.messages.PlcSubscriptionEvent;
import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
+import org.apache.plc4x.java.api.metadata.Metadata;
+import org.apache.plc4x.java.spi.metadata.DefaultMetadata;
import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
import org.apache.plc4x.java.api.model.PlcTag;
import org.apache.plc4x.java.api.value.PlcValue;
@@ -34,7 +37,6 @@
import org.apache.plc4x.java.opcua.readwrite.*;
import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionEvent;
import org.apache.plc4x.java.spi.messages.utils.PlcResponseItem;
-import org.apache.plc4x.java.spi.messages.utils.PlcTagItem;
import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration;
import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionTag;
import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionHandle;
@@ -260,17 +262,22 @@ public void stopSubscriber() {
* @param values - array of data values to be sent to the client.
*/
private void onSubscriptionValue(MonitoredItemNotification[] values) {
- LinkedHashSet tagNameList = new LinkedHashSet<>();
+ long receiveTs = System.currentTimeMillis();
+ Metadata responseMetadata = new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.RECEIVE_TIMESTAMP, receiveTs)
+ .build();
+
List dataValues = new ArrayList<>(values.length);
Map tagMap = new LinkedHashMap<>();
for (MonitoredItemNotification value : values) {
String tagName = tagNames.get((int) value.getClientHandle() - 1);
- tagNameList.add(tagName);
tagMap.put(tagName, subscriptionRequest.getTag(tagName).getTag());
dataValues.add(value.getValue());
}
- Map> tags = plcSubscriber.readResponse(tagNameList, tagMap, dataValues);
- final PlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent(Instant.now(), tags);
+
+ Map metadata = new HashMap<>();
+ Map> tags = plcSubscriber.readResponse(tagMap, dataValues, metadata, responseMetadata);
+ final PlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent(Instant.now(), tags, metadata);
consumers.forEach(plcSubscriptionEventConsumer -> plcSubscriptionEventConsumer.accept(event));
}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/tag/OpcuaQualityStatus.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/tag/OpcuaQualityStatus.java
new file mode 100644
index 00000000000..1500e210999
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/tag/OpcuaQualityStatus.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.opcua.tag;
+
+import org.apache.plc4x.java.opcua.readwrite.StatusCode;
+
+public final class OpcuaQualityStatus {
+
+ private static final long STATUS_MASK = 0xC0000000L;
+ private static final long STATUS_GOOD = 0x00000000L;
+ private static final long STATUS_UNCERTAIN = 0x40000000L;
+ private static final long STATUS_BAD = 0x80000000L;
+
+ private final StatusCode statusCode;
+
+ public OpcuaQualityStatus(StatusCode statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public boolean isGood() {
+ return (statusCode.getStatusCode() & STATUS_MASK) == STATUS_GOOD;
+ }
+
+ public boolean isBad() {
+ return (statusCode.getStatusCode() & STATUS_MASK) == STATUS_BAD;
+ }
+
+ public boolean isUncertain() {
+ return (statusCode.getStatusCode() & STATUS_MASK) == STATUS_UNCERTAIN;
+ }
+
+ @Override
+ public String toString() {
+ if (isGood()) {
+ return "good";
+ } else if (isBad()) {
+ return "bad";
+ }
+ return "uncertain";
+ }
+}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/KeystoreGenerator.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/KeystoreGenerator.java
new file mode 100644
index 00000000000..c16f0b80e04
--- /dev/null
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/KeystoreGenerator.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.opcua;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+import java.util.Set;
+import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
+import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
+
+/**
+ * Utility to generate server certificate - based on Eclipse Milo stuff.
+ */
+public class KeystoreGenerator {
+
+ private final String password;
+ private final KeyStore keyStore;
+ private final X509Certificate certificate;
+
+ public KeystoreGenerator(String password, int length, String applicationUri) {
+ this(password, length, applicationUri, "server-ai", "Milo Server");
+ }
+
+ public KeystoreGenerator(String password, int length, String applicationUri, String entryName, String commonName) {
+ this.password = password;
+ try {
+ this.keyStore = generate(password, length, applicationUri, entryName, commonName);
+
+ Key serverPrivateKey = keyStore.getKey(entryName, password.toCharArray());
+ if (serverPrivateKey instanceof PrivateKey) {
+ this.certificate = (X509Certificate) keyStore.getCertificate(entryName);
+ } else {
+ throw new IllegalStateException("Unexpected keystore entry, expected private key");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private KeyStore generate(String password, int length, String applicationUri, String entryName, String commonName) throws Exception {
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ keyStore.load(null, password.toCharArray());
+ KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(length);
+ SelfSignedCertificateBuilder builder = (new SelfSignedCertificateBuilder(
+ keyPair)).setCommonName(commonName)
+ .setOrganization("Apache Software Foundation")
+ .setOrganizationalUnit("PLC4X")
+ .setLocalityName("PLC4J")
+ .setStateName("CA")
+ .setCountryCode("US")
+ .setApplicationUri(applicationUri);
+
+ Set hostnames = Set.of("127.0.0.1");
+
+ for (String hostname : hostnames) {
+ if (hostname.startsWith("\\d+\\.")) {
+ builder.addIpAddress(hostname);
+ } else {
+ builder.addDnsName(hostname);
+ }
+ }
+
+ X509Certificate certificate = builder.build();
+ keyStore.setKeyEntry(entryName, keyPair.getPrivate(), password.toCharArray(), new X509Certificate[]{ certificate });
+ return keyStore;
+ }
+
+ public KeyStore getKeyStore() {
+ return keyStore;
+ }
+
+ public X509Certificate getCertificate() {
+ return certificate;
+ }
+
+ public void writeKeyStoreTo(OutputStream stream) throws IOException, GeneralSecurityException {
+ keyStore.store(stream, password.toCharArray());
+ stream.flush();
+ }
+
+ public void writeCertificateTo(OutputStream stream) throws IOException, CertificateEncodingException {
+ String data = "-----BEGIN CERTIFICATE-----\n" +
+ Base64.getMimeEncoder(64, "\n".getBytes()).encodeToString(certificate.getEncoded()) + "\n" +
+ "-----END CERTIFICATE-----";
+
+ stream.write(data.getBytes());
+ stream.flush();
+ }
+
+}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/MiloTestContainer.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/MiloTestContainer.java
index db13a936aee..43989e2659e 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/MiloTestContainer.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/MiloTestContainer.java
@@ -36,8 +36,15 @@ public class MiloTestContainer extends GenericContainer {
public MiloTestContainer() {
super(IMAGE);
- waitingFor(Wait.forLogMessage("Server started\\s*", 1));
+ waitingFor(Wait.forLogMessage("Server started\\s*", 1))
+ // Uncomment below to debug Milo server
+ //.withStartupTimeout(Duration.ofMinutes(10))
+ ;
addExposedPort(12686);
+
+ // Uncomment below to enable server debug
+ //withEnv("JAVA_TOOL_OPTIONS", "-agentlib:jdwp=transport=dt_socket,address=*:8000,server=y,suspend=y");
+ //addFixedExposedPort(8000, 8000);
}
private static ImageFromDockerfile inlineImage() {
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index 01432165a00..2e6bf163ddb 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -18,6 +18,8 @@
*/
package org.apache.plc4x.java.opcua;
+import java.io.File;
+import java.io.FileOutputStream;
import java.lang.reflect.Array;
import java.net.URLEncoder;
import java.nio.charset.Charset;
@@ -45,10 +47,8 @@
import org.apache.plc4x.java.opcua.security.MessageSecurity;
import org.apache.plc4x.java.opcua.security.SecurityPolicy;
import org.apache.plc4x.java.opcua.tag.OpcuaTag;
-import org.apache.plc4x.test.DisableOnJenkinsFlag;
import org.assertj.core.api.Condition;
import org.assertj.core.api.SoftAssertions;
-import org.eclipse.milo.examples.server.TestMiloServer;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -59,15 +59,9 @@
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;
-import org.testcontainers.containers.BindMode;
-import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
-import org.testcontainers.containers.wait.strategy.Wait;
-import org.testcontainers.images.builder.ImageFromDockerfile;
-import org.testcontainers.jib.JibImage;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@@ -75,17 +69,23 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
-@DisableOnJenkinsFlag
@Testcontainers(disabledWithoutDocker = true)
public class OpcuaPlcDriverTest {
private static final Logger LOGGER = LoggerFactory.getLogger(OpcuaPlcDriverTest.class);
+ private static final String APPLICATION_URI = "urn:org.apache:plc4x";
+ private static final KeystoreGenerator SERVER_KEY_STORE_GENERATOR = new KeystoreGenerator("password", 2048, APPLICATION_URI);
+ private static final KeystoreGenerator CLIENT_KEY_STORE_GENERATOR = new KeystoreGenerator("changeit", 2048, APPLICATION_URI, "plc4x_plus_milo", "client");
+
@Container
- public final GenericContainer milo = new MiloTestContainer()
+ public final MiloTestContainer milo = new MiloTestContainer()
//.withCreateContainerCmdModifier(cmd -> cmd.withHostName("test-opcua-server"))
.withLogConsumer(new Slf4jLogConsumer(LOGGER))
- .withFileSystemBind("target/tmp/server/security", "/tmp/server/security", BindMode.READ_WRITE);
+ .withFileSystemBind(SECURITY_DIR.getAbsolutePath(), "/tmp/server/security")
+ //.withEnv("JAVA_TOOL_OPTIONS", "-agentlib:jdwp=transport=dt_socket,address=*:8000,server=y,suspend=y")
+// .withCommand("java -cp '/opt/milo/*:/opt/milo/' org.eclipse.milo.examples.server.TestMiloServer")
+ ;
// Read only variables of milo example server of version 3.6
private static final String BOOL_IDENTIFIER_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/Boolean";
@@ -142,8 +142,8 @@ public class OpcuaPlcDriverTest {
//Tcp pattern of OPC UA
private final String opcPattern = "opcua:tcp://";
- private final String paramSectionDivider = "?";
- private final String paramDivider = "&";
+ private static final String PARAM_SECTION_DIVIDER = "?";
+ private static final String PARAM_DIVIDER = "&";
private final String discoveryValidParamTrue = "discovery=true";
private final String discoveryValidParamFalse = "discovery=false";
@@ -155,35 +155,39 @@ public class OpcuaPlcDriverTest {
final List discoveryParamValidSet = List.of(discoveryValidParamTrue, discoveryValidParamFalse);
List discoveryParamCorruptedSet = List.of(discoveryCorruptedParamWrongValueNum, discoveryCorruptedParamWrongName);
-
- @BeforeEach
- public void startUp() {
- //System.out.println(milo.getMappedPort(12686));
- tcpConnectionAddress = String.format(opcPattern + miloLocalAddress, milo.getHost(), milo.getMappedPort(12686)) + "?endpoint-port=12686";
- connectionStringValidSet = List.of(tcpConnectionAddress);
- }
+ private static File SECURITY_DIR;
+ private static File CLIENT_KEY_STORE;
@BeforeAll
- public static void setup() throws Exception {
- // When switching JDK versions from a newer to an older version,
- // this can cause the server to not start correctly.
- // Deleting the directory makes sure the key-store is initialized correctly.
-// Path securityBaseDir = Paths.get(System.getProperty("java.io.tmpdir"), "server", "security");
-// try {
-// Files.delete(securityBaseDir);
-// } catch (Exception e) {
-// // Ignore this ...
-// }
-//
-// exampleServer = new TestMiloServer();
-// exampleServer.startup().get();
+ public static void prepare() throws Exception {
+ Path tempDirectory = Files.createTempDirectory("plc4x_opcua_client");
+
+ SECURITY_DIR = new File(tempDirectory.toFile().getAbsolutePath(), "server/security");
+ File pkiDir = new File(SECURITY_DIR, "pki");
+ File trustedCerts = new File(pkiDir, "trusted/certs");
+ if (!pkiDir.mkdirs() || !trustedCerts.mkdirs()) {
+ throw new IllegalStateException("Could not start test - missing permissions to create temporary files");
+ }
+
+ // pre-provisioned server certificate
+ try (FileOutputStream bos = new FileOutputStream(new File(pkiDir.getParentFile(), "example-server.pfx"))) {
+ SERVER_KEY_STORE_GENERATOR.writeKeyStoreTo(bos);
+ }
+
+ // pre-provisioned client certificate, doing it here because server might be slow in picking up them, and we don't want to wait with our tests
+ CLIENT_KEY_STORE = Files.createTempFile("plc4x_opcua_client_", ".p12").toAbsolutePath().toFile();
+ try (FileOutputStream outputStream = new FileOutputStream(CLIENT_KEY_STORE)) {
+ CLIENT_KEY_STORE_GENERATOR.writeKeyStoreTo(outputStream);
+ }
+ try (FileOutputStream outputStream = new FileOutputStream(new File(trustedCerts, "plc4x.crt"))) {
+ CLIENT_KEY_STORE_GENERATOR.writeCertificateTo(outputStream);
+ }
}
- @AfterAll
- public static void tearDown() throws Exception {
-// if (exampleServer != null) {
-// exampleServer.shutdown().get();
-// }
+ @BeforeEach
+ public void startUp() throws Exception {
+ tcpConnectionAddress = String.format(opcPattern + miloLocalAddress, milo.getHost(), milo.getMappedPort(12686)) + "?endpoint-port=12686";
+ connectionStringValidSet = List.of(tcpConnectionAddress);
}
@Nested
@@ -276,7 +280,7 @@ Stream connectionWithDiscoveryParam() throws Exception {
return connectionStringValidSet.stream()
.map(connectionAddress -> DynamicContainer.dynamicContainer(connectionAddress, () ->
discoveryParamValidSet.stream().map(discoveryParam -> DynamicTest.dynamicTest(discoveryParam, () -> {
- String connectionString = connectionAddress + paramDivider + discoveryParam;
+ String connectionString = connectionAddress + PARAM_DIVIDER + discoveryParam;
PlcConnection opcuaConnection = new DefaultPlcDriverManager().getConnection(connectionString);
Condition is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
assertThat(opcuaConnection).is(is_connected);
@@ -340,6 +344,39 @@ void connectionWithPlcAuthenticationOverridesUrlParam() throws Exception {
assertThat(response.getResponseCode("String")).isEqualTo(PlcResponseCode.OK);
}
}
+
+ @Test
+ void staticConfig() throws Exception {
+ DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
+
+ File certificateFile = Files.createTempFile("plc4x_opcua_server_", ".crt").toAbsolutePath().toFile();
+ try (FileOutputStream outputStream = new FileOutputStream(certificateFile)) {
+ SERVER_KEY_STORE_GENERATOR.writeCertificateTo(outputStream);
+ }
+
+ String options = params(
+ entry("discovery", "false"),
+ entry("server-certificate-file", certificateFile.toString().replace("\\", "/")),
+ entry("key-store-file", CLIENT_KEY_STORE.toString().replace("\\", "/")), // handle windows paths
+ entry("key-store-password", "changeit"),
+ entry("key-store-type", "pkcs12"),
+ entry("security-policy", SecurityPolicy.Basic256Sha256.name()),
+ entry("message-security", MessageSecurity.SIGN.name())
+ );
+ try (PlcConnection opcuaConnection = driverManager.getConnection(tcpConnectionAddress + PARAM_DIVIDER
+ + options)) {
+ Condition is_connected = new Condition<>(PlcConnection::isConnected, "is connected");
+ assertThat(opcuaConnection).is(is_connected);
+
+ PlcReadRequest.Builder builder = opcuaConnection.readRequestBuilder()
+ .addTagAddress("String", STRING_IDENTIFIER_READ_WRITE);
+
+ PlcReadRequest request = builder.build();
+ PlcReadResponse response = request.execute().get();
+
+ assertThat(response.getResponseCode("String")).isEqualTo(PlcResponseCode.OK);
+ }
+ }
}
@Nested
@@ -533,7 +570,7 @@ public void run() {
assert !opcuaConnection.isConnected();
}
- private String getConnectionString(SecurityPolicy policy, MessageSecurity messageSecurity) {
+ private String getConnectionString(SecurityPolicy policy, MessageSecurity messageSecurity) throws Exception {
switch (policy) {
case NONE:
return tcpConnectionAddress;
@@ -543,18 +580,15 @@ private String getConnectionString(SecurityPolicy policy, MessageSecurity messag
case Basic256Sha256:
case Aes128_Sha256_RsaOaep:
case Aes256_Sha256_RsaPss:
- // this file and its contents should be populated by milo container
- Path keyStoreFile = Paths.get("target/tmp/server/security/example-server.pfx");
- String connectionParams = Stream.of(
- entry("key-store-file", keyStoreFile.toAbsolutePath().toString().replace("\\", "/")), // handle windows paths
- entry("key-store-password", "password"),
- entry("security-policy", policy.name()),
- entry("message-security", messageSecurity.name())
- )
- .map(tuple -> tuple.getKey() + "=" + URLEncoder.encode(tuple.getValue(), Charset.defaultCharset()))
- .collect(Collectors.joining(paramDivider));
-
- return tcpConnectionAddress + paramDivider + connectionParams;
+ String connectionParams = params(
+ entry("key-store-file", CLIENT_KEY_STORE.getAbsoluteFile().toString().replace("\\", "/")), // handle windows paths
+ entry("key-store-password", "changeit"),
+ entry("key-store-type", "pkcs12"),
+ entry("security-policy", policy.name()),
+ entry("message-security", messageSecurity.name())
+ );
+
+ return tcpConnectionAddress + PARAM_DIVIDER + connectionParams;
default:
throw new IllegalStateException();
}
@@ -582,4 +616,10 @@ private static Stream getConnectionSecurityPolicies() {
Arguments.of(SecurityPolicy.Aes256_Sha256_RsaPss, MessageSecurity.SIGN_ENCRYPT)
);
}
+
+ private static String params(Entry ... entries) {
+ return Stream.of(entries)
+ .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), Charset.defaultCharset()))
+ .collect(Collectors.joining(PARAM_DIVIDER));
+ }
}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java
index 094e09bb3b1..37dec0d08f7 100644
--- a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaSubscriptionHandleTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.plc4x.java.opcua.protocol;
+import java.io.ByteArrayOutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Stream;
import org.apache.plc4x.java.DefaultPlcDriverManager;
@@ -27,8 +28,7 @@
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.opcua.MiloTestContainer;
import org.apache.plc4x.java.opcua.OpcuaPlcDriverTest;
-import org.apache.plc4x.test.DisableOnJenkinsFlag;
-import org.apache.plc4x.test.DisableOnParallelsVmFlag;
+import org.apache.plc4x.java.opcua.KeystoreGenerator;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -36,13 +36,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;
-import org.testcontainers.containers.BindMode;
-import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
+import org.testcontainers.images.builder.Transferable;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@@ -56,18 +52,14 @@
// cdutz: I have done way more than my fair share on tracking down this issue and am simply giving up on it.
// I tracked it down into the core of Milo several times now, but got lost in there.
// It's not a big issue as the GitHub runners and the Apache Jenkins still run the test.
-@DisableOnJenkinsFlag
-@DisableOnParallelsVmFlag
@Testcontainers(disabledWithoutDocker = true)
public class OpcuaSubscriptionHandleTest {
private static final Logger LOGGER = LoggerFactory.getLogger(OpcuaPlcDriverTest.class);
@Container
- public final GenericContainer milo = new MiloTestContainer()
- //.withCreateContainerCmdModifier(cmd -> cmd.withHostName("test-opcua-server"))
- .withLogConsumer(new Slf4jLogConsumer(LOGGER))
- .withFileSystemBind("target/tmp/server/security", "/tmp/server/security", BindMode.READ_WRITE);
+ public final MiloTestContainer milo = new MiloTestContainer()
+ .withLogConsumer(new Slf4jLogConsumer(LOGGER));
// Address of local milo server
private static final String miloLocalAddress = "%s:%d/milo";
@@ -102,16 +94,7 @@ public void setup() throws Exception {
// When switching JDK versions from a newer to an older version,
// this can cause the server to not start correctly.
// Deleting the directory makes sure the key-store is initialized correctly.
-
String tcpConnectionAddress = String.format(opcPattern + miloLocalAddress, milo.getHost(), milo.getMappedPort(12686)) + "?endpoint-port=12686";
-
- Path securityBaseDir = Paths.get(System.getProperty("java.io.tmpdir"), "server", "security");
- try {
- Files.delete(securityBaseDir);
- } catch (Exception e) {
- // Ignore this ...
- }
-
//Connect
opcuaConnection = new DefaultPlcDriverManager().getConnection(tcpConnectionAddress);
assertThat(opcuaConnection).extracting(PlcConnection::isConnected).isEqualTo(true);
diff --git a/plc4j/drivers/opcua/src/test/java/org/eclipse/milo/examples/server/TestMiloServer.java b/plc4j/drivers/opcua/src/test/java/org/eclipse/milo/examples/server/TestMiloServer.java
index 872afbfb0fd..d886afb11c4 100644
--- a/plc4j/drivers/opcua/src/test/java/org/eclipse/milo/examples/server/TestMiloServer.java
+++ b/plc4j/drivers/opcua/src/test/java/org/eclipse/milo/examples/server/TestMiloServer.java
@@ -123,8 +123,6 @@ public TestMiloServer() throws Exception {
);
DefaultTrustListManager trustListManager = new DefaultTrustListManager(pkiDir);
- trustListManager.setTrustedCertificates(new ArrayList<>(certificateManager.getCertificates()));
-
DefaultServerCertificateValidator certificateValidator =
new DefaultServerCertificateValidator(trustListManager);
diff --git a/plc4j/drivers/opcua/src/test/resources/logback-test.xml b/plc4j/drivers/opcua/src/test/resources/logback-test.xml
index 695109a5329..719321b8e43 100644
--- a/plc4j/drivers/opcua/src/test/resources/logback-test.xml
+++ b/plc4j/drivers/opcua/src/test/resources/logback-test.xml
@@ -32,4 +32,6 @@
+
+
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7AlarmEvent.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7AlarmEvent.java
index 931bfab0a85..5d08cc6104e 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7AlarmEvent.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7AlarmEvent.java
@@ -18,6 +18,7 @@
*/
package org.apache.plc4x.java.s7.events;
+import java.util.Collections;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.model.PlcTag;
@@ -33,7 +34,7 @@
import java.util.List;
import java.util.Map;
-public class S7AlarmEvent implements S7Event {
+public class S7AlarmEvent extends S7EventBase {
public enum Fields {
@@ -130,172 +131,19 @@ public enum Fields {
}
- private final Instant timeStamp;
private final Map map;
- public S7AlarmEvent(Object obj) {
- this.map = new HashMap<>();
- if (obj instanceof S7PayloadAlarmAckInd) {
- AlarmMessageAckPushType msg = ((S7PayloadAlarmAckInd) obj).getAlarmMessage();
- DateAndTime dt = msg.getTimeStamp();
- int year = (dt.getYear() >= 90) ? dt.getYear() + 1900 : dt.getYear() + 2000;
- LocalDateTime ldt = LocalDateTime.of(year,
- dt.getMonth(),
- dt.getDay(),
- dt.getHour(),
- dt.getMinutes(),
- dt.getSeconds(),
- dt.getMsec() * 1000000);
- this.timeStamp = ldt.toInstant(ZoneOffset.UTC);
- map.put(S7SysEvent.Fields.TIMESTAMP.name(), this.timeStamp);
-
- List items = msg.getMessageObjects();
- for (AlarmMessageAckObjectPushType item : items) {
- map.put(Fields.EVENT_ID.name(), item.getEventId());
- map.put(Fields.TYPE.name(), "ALARMACK_IND");
- map.put(Fields.ASSOCIATED_VALUES.name(), item.getNumberOfValues());
-
- map.put(Fields.SIG_1_DATA_GOING.name(), item.getAckStateGoing().getSIG_1());
- map.put(Fields.SIG_2_DATA_GOING.name(), item.getAckStateGoing().getSIG_2());
- map.put(Fields.SIG_3_DATA_GOING.name(), item.getAckStateGoing().getSIG_3());
- map.put(Fields.SIG_4_DATA_GOING.name(), item.getAckStateGoing().getSIG_4());
- map.put(Fields.SIG_5_DATA_GOING.name(), item.getAckStateGoing().getSIG_5());
- map.put(Fields.SIG_6_DATA_GOING.name(), item.getAckStateGoing().getSIG_6());
- map.put(Fields.SIG_7_DATA_GOING.name(), item.getAckStateGoing().getSIG_7());
- map.put(Fields.SIG_8_DATA_GOING.name(), item.getAckStateGoing().getSIG_8());
-
- map.put(Fields.SIG_1_DATA_COMING.name(), item.getAckStateComing().getSIG_1());
- map.put(Fields.SIG_2_DATA_COMING.name(), item.getAckStateComing().getSIG_2());
- map.put(Fields.SIG_3_DATA_COMING.name(), item.getAckStateComing().getSIG_3());
- map.put(Fields.SIG_4_DATA_COMING.name(), item.getAckStateComing().getSIG_4());
- map.put(Fields.SIG_5_DATA_COMING.name(), item.getAckStateComing().getSIG_5());
- map.put(Fields.SIG_6_DATA_COMING.name(), item.getAckStateComing().getSIG_6());
- map.put(Fields.SIG_7_DATA_COMING.name(), item.getAckStateComing().getSIG_7());
- map.put(Fields.SIG_8_DATA_COMING.name(), item.getAckStateComing().getSIG_8());
- }
-
- } else {
-
- AlarmMessagePushType msg = null;
-
- if (obj instanceof S7PayloadAlarm8) {
- msg = ((S7PayloadAlarm8) obj).getAlarmMessage();
- } else if (obj instanceof S7PayloadNotify) {
- msg = ((S7PayloadNotify) obj).getAlarmMessage();
- } else if (obj instanceof S7PayloadAlarmSQ) {
- msg = ((S7PayloadAlarmSQ) obj).getAlarmMessage();
- } else if (obj instanceof S7PayloadAlarmS) {
- msg = ((S7PayloadAlarmS) obj).getAlarmMessage();
- } else if (obj instanceof S7PayloadNotify8) {
- msg = ((S7PayloadNotify8) obj).getAlarmMessage();
- } else {
- throw new PlcRuntimeException("Unsupported type: " + obj.getClass().getName());
- }
-
- DateAndTime dt = msg.getTimeStamp();
- int year = (dt.getYear() >= 90) ? dt.getYear() + 1900 : dt.getYear() + 2000;
- LocalDateTime ldt = LocalDateTime.of(year,
- dt.getMonth(),
- dt.getDay(),
- dt.getHour(),
- dt.getMinutes(),
- dt.getSeconds(),
- dt.getMsec() * 1000000);
- this.timeStamp = ldt.toInstant(ZoneOffset.UTC);
- map.put(S7SysEvent.Fields.TIMESTAMP.name(), this.timeStamp);
-
- List items = msg.getMessageObjects();
- for (AlarmMessageObjectPushType item : items) {
- map.put(Fields.EVENT_ID.name(), item.getEventId());
-
- if (obj instanceof S7PayloadAlarm8)
- map.put(Fields.TYPE.name(), "ALARM8");
- if (obj instanceof S7PayloadNotify)
- map.put(Fields.TYPE.name(), "NOTIFY");
- if (obj instanceof S7PayloadAlarmSQ)
- map.put(Fields.TYPE.name(), "ALARMSQ");
- if (obj instanceof S7PayloadAlarmS)
- map.put(Fields.TYPE.name(), "ALARMS");
- if (obj instanceof S7PayloadNotify8)
- map.put(Fields.TYPE.name(), "NOTIFY8");
-
-
- map.put(Fields.ASSOCIATED_VALUES.name(), item.getNumberOfValues());
-
-
- map.put(Fields.SIG_1.name(), item.getEventState().getSIG_1());
- map.put(Fields.SIG_2.name(), item.getEventState().getSIG_2());
- map.put(Fields.SIG_3.name(), item.getEventState().getSIG_3());
- map.put(Fields.SIG_4.name(), item.getEventState().getSIG_4());
- map.put(Fields.SIG_5.name(), item.getEventState().getSIG_5());
- map.put(Fields.SIG_6.name(), item.getEventState().getSIG_6());
- map.put(Fields.SIG_7.name(), item.getEventState().getSIG_7());
- map.put(Fields.SIG_8.name(), item.getEventState().getSIG_8());
-
-
- map.put(Fields.SIG_1_STATE.name(), item.getLocalState().getSIG_1());
- map.put(Fields.SIG_2_STATE.name(), item.getLocalState().getSIG_2());
- map.put(Fields.SIG_3_STATE.name(), item.getLocalState().getSIG_3());
- map.put(Fields.SIG_4_STATE.name(), item.getLocalState().getSIG_4());
- map.put(Fields.SIG_5_STATE.name(), item.getLocalState().getSIG_5());
- map.put(Fields.SIG_6_STATE.name(), item.getLocalState().getSIG_6());
- map.put(Fields.SIG_7_STATE.name(), item.getLocalState().getSIG_7());
- map.put(Fields.SIG_8_STATE.name(), item.getLocalState().getSIG_8());
-
- map.put(Fields.SIG_1_DATA_GOING.name(), item.getAckStateGoing().getSIG_1());
- map.put(Fields.SIG_2_DATA_GOING.name(), item.getAckStateGoing().getSIG_2());
- map.put(Fields.SIG_3_DATA_GOING.name(), item.getAckStateGoing().getSIG_3());
- map.put(Fields.SIG_4_DATA_GOING.name(), item.getAckStateGoing().getSIG_4());
- map.put(Fields.SIG_5_DATA_GOING.name(), item.getAckStateGoing().getSIG_5());
- map.put(Fields.SIG_6_DATA_GOING.name(), item.getAckStateGoing().getSIG_6());
- map.put(Fields.SIG_7_DATA_GOING.name(), item.getAckStateGoing().getSIG_7());
- map.put(Fields.SIG_8_DATA_GOING.name(), item.getAckStateGoing().getSIG_8());
-
- map.put(Fields.SIG_1_DATA_COMING.name(), item.getAckStateComing().getSIG_1());
- map.put(Fields.SIG_2_DATA_COMING.name(), item.getAckStateComing().getSIG_2());
- map.put(Fields.SIG_3_DATA_COMING.name(), item.getAckStateComing().getSIG_3());
- map.put(Fields.SIG_4_DATA_COMING.name(), item.getAckStateComing().getSIG_4());
- map.put(Fields.SIG_5_DATA_COMING.name(), item.getAckStateComing().getSIG_5());
- map.put(Fields.SIG_6_DATA_COMING.name(), item.getAckStateComing().getSIG_6());
- map.put(Fields.SIG_7_DATA_COMING.name(), item.getAckStateComing().getSIG_7());
- map.put(Fields.SIG_8_DATA_COMING.name(), item.getAckStateComing().getSIG_8());
-
- List values = item.getAssociatedValues();
- int i = 1;
- int j = 0;
- for (AssociatedValueType value : values) {
- map.put("SIG_" + i + "_DATA_STATUS", value.getReturnCode().getValue());
- map.put("SIG_" + i + "_DATA_SIZE", value.getTransportSize().getValue());
- map.put("SIG_" + i + "_DATA_LENGTH", value.getValueLength());
- byte[] data = new byte[value.getData().size()];
- j = 0;
- for (short s : value.getData()) {
- data[j] = (byte) s;
- j++;
- }
- map.put("SIG_" + i + "_DATA", data);
- i++;
- }
-
- }
-
- }
-
+ S7AlarmEvent(Instant timestamp, Map obj) {
+ super(timestamp);
+ this.map = obj;
}
- ;
-
@Override
public Map getMap() {
return map;
}
- @Override
- public Instant getTimestamp() {
- return timeStamp;
- }
-
@Override
public PlcReadRequest getRequest() {
throw new UnsupportedOperationException("Not supported yet.");
@@ -671,5 +519,160 @@ public PlcResponseCode getResponseCode(String name) {
throw new UnsupportedOperationException("Not supported yet.");
}
+ public static S7AlarmEvent of(Object obj) {
+ if (obj instanceof S7PayloadAlarmAckInd) {
+ AlarmMessageAckPushType msg = ((S7PayloadAlarmAckInd) obj).getAlarmMessage();
+ DateAndTime dt = msg.getTimeStamp();
+ int year = (dt.getYear() >= 90) ? dt.getYear() + 1900 : dt.getYear() + 2000;
+ LocalDateTime ldt = LocalDateTime.of(year,
+ dt.getMonth(),
+ dt.getDay(),
+ dt.getHour(),
+ dt.getMinutes(),
+ dt.getSeconds(),
+ dt.getMsec() * 1000000);
+ Instant timeStamp = ldt.toInstant(ZoneOffset.UTC);
+
+ Map map = new HashMap<>();
+ map.put(S7SysEvent.Fields.TIMESTAMP.name(), timeStamp);
+
+ List items = msg.getMessageObjects();
+ for (AlarmMessageAckObjectPushType item : items) {
+ map.put(Fields.EVENT_ID.name(), item.getEventId());
+ map.put(Fields.TYPE.name(), "ALARMACK_IND");
+ map.put(Fields.ASSOCIATED_VALUES.name(), item.getNumberOfValues());
+
+ map.put(Fields.SIG_1_DATA_GOING.name(), item.getAckStateGoing().getSIG_1());
+ map.put(Fields.SIG_2_DATA_GOING.name(), item.getAckStateGoing().getSIG_2());
+ map.put(Fields.SIG_3_DATA_GOING.name(), item.getAckStateGoing().getSIG_3());
+ map.put(Fields.SIG_4_DATA_GOING.name(), item.getAckStateGoing().getSIG_4());
+ map.put(Fields.SIG_5_DATA_GOING.name(), item.getAckStateGoing().getSIG_5());
+ map.put(Fields.SIG_6_DATA_GOING.name(), item.getAckStateGoing().getSIG_6());
+ map.put(Fields.SIG_7_DATA_GOING.name(), item.getAckStateGoing().getSIG_7());
+ map.put(Fields.SIG_8_DATA_GOING.name(), item.getAckStateGoing().getSIG_8());
+
+ map.put(Fields.SIG_1_DATA_COMING.name(), item.getAckStateComing().getSIG_1());
+ map.put(Fields.SIG_2_DATA_COMING.name(), item.getAckStateComing().getSIG_2());
+ map.put(Fields.SIG_3_DATA_COMING.name(), item.getAckStateComing().getSIG_3());
+ map.put(Fields.SIG_4_DATA_COMING.name(), item.getAckStateComing().getSIG_4());
+ map.put(Fields.SIG_5_DATA_COMING.name(), item.getAckStateComing().getSIG_5());
+ map.put(Fields.SIG_6_DATA_COMING.name(), item.getAckStateComing().getSIG_6());
+ map.put(Fields.SIG_7_DATA_COMING.name(), item.getAckStateComing().getSIG_7());
+ map.put(Fields.SIG_8_DATA_COMING.name(), item.getAckStateComing().getSIG_8());
+ }
+ return new S7AlarmEvent(timeStamp, map);
+ } else {
+
+ AlarmMessagePushType msg = null;
+
+ if (obj instanceof S7PayloadAlarm8) {
+ msg = ((S7PayloadAlarm8) obj).getAlarmMessage();
+ } else if (obj instanceof S7PayloadNotify) {
+ msg = ((S7PayloadNotify) obj).getAlarmMessage();
+ } else if (obj instanceof S7PayloadAlarmSQ) {
+ msg = ((S7PayloadAlarmSQ) obj).getAlarmMessage();
+ } else if (obj instanceof S7PayloadAlarmS) {
+ msg = ((S7PayloadAlarmS) obj).getAlarmMessage();
+ } else if (obj instanceof S7PayloadNotify8) {
+ msg = ((S7PayloadNotify8) obj).getAlarmMessage();
+ } else {
+ throw new PlcRuntimeException("Unsupported type: " + obj.getClass().getName());
+ }
+
+ DateAndTime dt = msg.getTimeStamp();
+ int year = (dt.getYear() >= 90) ? dt.getYear() + 1900 : dt.getYear() + 2000;
+ LocalDateTime ldt = LocalDateTime.of(year,
+ dt.getMonth(),
+ dt.getDay(),
+ dt.getHour(),
+ dt.getMinutes(),
+ dt.getSeconds(),
+ dt.getMsec() * 1000000);
+ Instant timeStamp = ldt.toInstant(ZoneOffset.UTC);
+
+ Map map = new HashMap<>();
+ map.put(S7SysEvent.Fields.TIMESTAMP.name(), timeStamp);
+
+ List items = msg.getMessageObjects();
+ for (AlarmMessageObjectPushType item : items) {
+ map.put(Fields.EVENT_ID.name(), item.getEventId());
+
+ if (obj instanceof S7PayloadAlarm8) {
+ map.put(Fields.TYPE.name(), "ALARM8");
+ }
+ if (obj instanceof S7PayloadNotify) {
+ map.put(Fields.TYPE.name(), "NOTIFY");
+ }
+ if (obj instanceof S7PayloadAlarmSQ) {
+ map.put(Fields.TYPE.name(), "ALARMSQ");
+ }
+ if (obj instanceof S7PayloadAlarmS) {
+ map.put(Fields.TYPE.name(), "ALARMS");
+ }
+ if (obj instanceof S7PayloadNotify8) {
+ map.put(Fields.TYPE.name(), "NOTIFY8");
+ }
+
+ map.put(Fields.ASSOCIATED_VALUES.name(), item.getNumberOfValues());
+
+ map.put(Fields.SIG_1.name(), item.getEventState().getSIG_1());
+ map.put(Fields.SIG_2.name(), item.getEventState().getSIG_2());
+ map.put(Fields.SIG_3.name(), item.getEventState().getSIG_3());
+ map.put(Fields.SIG_4.name(), item.getEventState().getSIG_4());
+ map.put(Fields.SIG_5.name(), item.getEventState().getSIG_5());
+ map.put(Fields.SIG_6.name(), item.getEventState().getSIG_6());
+ map.put(Fields.SIG_7.name(), item.getEventState().getSIG_7());
+ map.put(Fields.SIG_8.name(), item.getEventState().getSIG_8());
+
+
+ map.put(Fields.SIG_1_STATE.name(), item.getLocalState().getSIG_1());
+ map.put(Fields.SIG_2_STATE.name(), item.getLocalState().getSIG_2());
+ map.put(Fields.SIG_3_STATE.name(), item.getLocalState().getSIG_3());
+ map.put(Fields.SIG_4_STATE.name(), item.getLocalState().getSIG_4());
+ map.put(Fields.SIG_5_STATE.name(), item.getLocalState().getSIG_5());
+ map.put(Fields.SIG_6_STATE.name(), item.getLocalState().getSIG_6());
+ map.put(Fields.SIG_7_STATE.name(), item.getLocalState().getSIG_7());
+ map.put(Fields.SIG_8_STATE.name(), item.getLocalState().getSIG_8());
+
+ map.put(Fields.SIG_1_DATA_GOING.name(), item.getAckStateGoing().getSIG_1());
+ map.put(Fields.SIG_2_DATA_GOING.name(), item.getAckStateGoing().getSIG_2());
+ map.put(Fields.SIG_3_DATA_GOING.name(), item.getAckStateGoing().getSIG_3());
+ map.put(Fields.SIG_4_DATA_GOING.name(), item.getAckStateGoing().getSIG_4());
+ map.put(Fields.SIG_5_DATA_GOING.name(), item.getAckStateGoing().getSIG_5());
+ map.put(Fields.SIG_6_DATA_GOING.name(), item.getAckStateGoing().getSIG_6());
+ map.put(Fields.SIG_7_DATA_GOING.name(), item.getAckStateGoing().getSIG_7());
+ map.put(Fields.SIG_8_DATA_GOING.name(), item.getAckStateGoing().getSIG_8());
+
+ map.put(Fields.SIG_1_DATA_COMING.name(), item.getAckStateComing().getSIG_1());
+ map.put(Fields.SIG_2_DATA_COMING.name(), item.getAckStateComing().getSIG_2());
+ map.put(Fields.SIG_3_DATA_COMING.name(), item.getAckStateComing().getSIG_3());
+ map.put(Fields.SIG_4_DATA_COMING.name(), item.getAckStateComing().getSIG_4());
+ map.put(Fields.SIG_5_DATA_COMING.name(), item.getAckStateComing().getSIG_5());
+ map.put(Fields.SIG_6_DATA_COMING.name(), item.getAckStateComing().getSIG_6());
+ map.put(Fields.SIG_7_DATA_COMING.name(), item.getAckStateComing().getSIG_7());
+ map.put(Fields.SIG_8_DATA_COMING.name(), item.getAckStateComing().getSIG_8());
+
+ List values = item.getAssociatedValues();
+ int i = 1;
+ int j = 0;
+ for (AssociatedValueType value : values) {
+ map.put("SIG_" + i + "_DATA_STATUS", value.getReturnCode().getValue());
+ map.put("SIG_" + i + "_DATA_SIZE", value.getTransportSize().getValue());
+ map.put("SIG_" + i + "_DATA_LENGTH", value.getValueLength());
+ byte[] data = new byte[value.getData().size()];
+ j = 0;
+ for (short s : value.getData()) {
+ data[j] = (byte) s;
+ j++;
+ }
+ map.put("SIG_" + i + "_DATA", data);
+ i++;
+ }
+ }
+
+ return new S7AlarmEvent(timeStamp, map);
+ }
+
+ }
}
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java
index 6b7c83d3bf2..9c0d0fcd83b 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/events/S7CyclicEvent.java
@@ -17,12 +17,14 @@
* under the License.
*/
package org.apache.plc4x.java.s7.events;
-
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import static io.netty.buffer.Unpooled.wrappedBuffer;
+import org.apache.plc4x.java.api.messages.PlcMetadataKeys;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
+import org.apache.plc4x.java.spi.metadata.DefaultMetadata;
+import org.apache.plc4x.java.api.metadata.time.TimeSource;
import org.apache.plc4x.java.api.model.PlcTag;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.api.value.PlcValue;
@@ -31,7 +33,6 @@
import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItemCyclicServicesPush;
import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItemCyclicServicesSubscribeResponse;
import org.apache.plc4x.java.s7.readwrite.utils.StaticHelper;
-
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
@@ -43,8 +44,7 @@
import org.apache.plc4x.java.s7.readwrite.tag.S7Tag;
import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionTag;
import org.apache.plc4x.java.spi.values.DefaultPlcValueHandler;
-
-public class S7CyclicEvent implements S7Event {
+public class S7CyclicEvent extends S7EventBase implements S7Event {
public enum Fields {
TYPE,
@@ -57,110 +57,104 @@ public enum Fields {
TRANSPORTSIZE_,
DATA_
}
-
private final PlcSubscriptionRequest request;
-
- private final Instant timeStamp;
private final Map map;
-
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesPush event) {
+ super(Instant.now(), new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build()
+ );
this.map = new HashMap<>();
- this.timeStamp = Instant.now();
this.request = request;
map.put(Fields.TYPE.name(), "CYCEVENT");
- map.put(Fields.TIMESTAMP.name(), this.timeStamp);
+ map.put(Fields.TIMESTAMP.name(), getTimestamp());
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
- int[] n = new int[1];
+ int[] n = new int[1];
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
map.put(tagname, dataToPlcValue(tagname, request, event.getItems().get(i).getData()));
- n[0]++;
+ n[0]++;
});
-
}
-
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesChangeDrivenPush event) {
+ super(Instant.now(), new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build()
+ );
this.map = new HashMap<>();
- this.timeStamp = Instant.now();
this.request = request;
map.put(Fields.TYPE.name(), "CYCEVENT");
- map.put(Fields.TIMESTAMP.name(), this.timeStamp);
+ map.put(Fields.TIMESTAMP.name(), getTimestamp());
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
int[] n = new int[1];
-
+
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
map.put(tagname, dataToPlcValue(tagname, request, event.getItems().get(i).getData()));
- n[0]++;
+ n[0]++;
});
-
+
}
-
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesSubscribeResponse event) {
+ super(Instant.now(), new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build()
+ );
this.map = new HashMap<>();
- this.timeStamp = Instant.now();
this.request = request;
map.put(Fields.TYPE.name(), "CYCEVENT");
- map.put(Fields.TIMESTAMP.name(), this.timeStamp);
+ map.put(Fields.TIMESTAMP.name(), getTimestamp());
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
int[] n = new int[1];
-
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
map.put(tagname, dataToPlcValue(tagname, request, event.getItems().get(i).getData()));
- n[0]++;
- });
+ n[0]++;
+ });
}
-
public S7CyclicEvent(PlcSubscriptionRequest request, short jobid, S7PayloadUserDataItemCyclicServicesChangeDrivenSubscribeResponse event) {
+ super(Instant.now(), new DefaultMetadata.Builder()
+ .put(PlcMetadataKeys.TIMESTAMP_SOURCE, TimeSource.ASSUMPTION)
+ .build()
+ );
this.map = new HashMap<>();
- this.timeStamp = Instant.now();
this.request = request;
map.put(Fields.TYPE.name(), "CYCEVENT");
- map.put(Fields.TIMESTAMP.name(), this.timeStamp);
+ map.put(Fields.TIMESTAMP.name(), getTimestamp());
map.put(Fields.JOBID.name(), jobid);
map.put(Fields.ITEMSCOUNT.name(), event.getItemsCount());
int[] n = new int[1];
-
+
request.getTagNames().forEach(tagname -> {
int i = n[0];
map.put(Fields.RETURNCODE_.name() + i, event.getItems().get(i).getReturnCode().getValue());
map.put(Fields.TRANSPORTSIZE_.name() + i, event.getItems().get(i).getTransportSize().getValue());
map.put(tagname, dataToPlcValue(tagname, request, event.getItems().get(i).getData()));
- n[0]++;
- });
+ n[0]++;
+ });
}
-
@Override
public Map getMap() {
return this.map;
}
-
- @Override
- public Instant getTimestamp() {
- return this.timeStamp;
- }
-
@Override
public PlcReadRequest getRequest() {
throw new UnsupportedOperationException("Not supported yet.");
}
-
@Override
public PlcValue getAsPlcValue() {
throw new UnsupportedOperationException("Not supported yet.");
}
-
@Override
public PlcValue getPlcValue(String name) {
if (request.getTagNames().contains(name)) {
@@ -170,33 +164,27 @@ public PlcValue getPlcValue(String name) {
}
return null;
}
-
@Override
public int getNumberOfValues(String name) {
throw new UnsupportedOperationException("Not supported yet.");
}
-
@Override
public Object getObject(String name) {
if ("REQUEST".equals(name)) return request;
return null;
}
-
@Override
public Object getObject(String name, int index) {
throw new UnsupportedOperationException("Not supported yet.");
}
-
@Override
public Collection
diff --git a/protocols/umas/src/main/resources/protocols/umas/umas.mspec b/protocols/umas/src/main/resources/protocols/umas/umas.mspec
index 1b5a32b0c12..cf65be4c060 100644
--- a/protocols/umas/src/main/resources/protocols/umas/umas.mspec
+++ b/protocols/umas/src/main/resources/protocols/umas/umas.mspec
@@ -196,19 +196,16 @@
[simple uint 4 isArray]
[simple uint 4 dataSizeIndex]
[simple uint 16 block]
- [const uint 8 unknown1 0x01]
[simple uint 16 baseOffset]
- [simple uint 8 offset]
+ [simple uint 16 offset]
[optional uint 16 arrayLength 'isArray']
- [array byte recordData length 'isArray == 1 ? dataSizeIndex * arrayLength : dataSizeIndex']
+ [array byte recordData length 'isArray == 1 ? dataSizeIndex * arrayLength : dataSizeIndex']
]
[type UmasUnlocatedVariableReference
- [simple uint 8 dataType]
- [simple uint 8 unknown1]
+ [simple uint 16 dataType]
[simple uint 16 block]
- [simple uint 8 offset]
- [simple uint 8 baseOffset]
+ [simple uint 16 offset]
[simple uint 16 unknown4]
[simple uint 16 stringLength]
[manual vstring value 'STATIC_CALL("parseTerminatedString", readBuffer, stringLength)' 'STATIC_CALL("serializeTerminatedString", writeBuffer, value, stringLength)' '(stringLength * 8)']
@@ -238,24 +235,22 @@
[simple uint 32 memoryLength]
]
-
[dataIo DataItem(UmasDataType dataType, uint 16 numberOfValues)
[typeSwitch dataType,numberOfValues
['BOOL','1' BOOL
+ [reserved uint 7 '0x0000' ]
+ [simple bit value ]
+ ]
+ ['EBOOL','1' BOOL
// TODO: Possibly change the order of the bit and the reserved part.
[reserved uint 7 '0x0000' ]
[simple bit value ]
]
- ['BOOL' List
- // TODO: Handle adding some reserved bits at the end to fill up the last word.
- [array bit value count 'numberOfValues' ]
- ]
['BYTE','1' BYTE
- [simple uint 8 value]
+ [simple byte value]
]
['BYTE' List
- // TODO: If the number of values is odd, add a reserved byte
- [array bit value count 'numberOfValues * 8' ]
+ [array byte value count 'numberOfValues' ]
]
['WORD' WORD
[simple uint 16 value]
@@ -294,40 +289,66 @@
[array float 32 value count 'numberOfValues']
]
['STRING','1' STRING
- [manual vstring value 'STATIC_CALL("parseTerminatedStringBytes", readBuffer, numberOfValues)' 'STATIC_CALL("serializeTerminatedString", writeBuffer, value, numberOfValues)' '(numberOfValues * 8)']
+ [manual vstring value 'STATIC_CALL("parseTerminatedStringBytes", readBuffer, numberOfValues)' 'STATIC_CALL("serializeTerminatedString", writeBuffer, _value, numberOfValues)' '(numberOfValues * 8)']
]
['STRING' List
[array float 32 value count 'numberOfValues']
]
+ ['TIME','1' TIME
+ [simple uint 32 value]
+ ]
+ ['TIME' List
+ [array uint 32 value count 'numberOfValues']
+ ]
+ ['DATE','1' DATE
+ [simple uint 8 day encoding='BCD']
+ [simple uint 8 month encoding='BCD']
+ [simple uint 16 year encoding='BCD']
+ ]
+ ['TOD','1' TIME_OF_DAY
+ [simple uint 32 value]
+ ]
+ ['TOD' List
+ [array uint 32 value count 'numberOfValues']
+ ]
+ ['DATE_AND_TIME','1' DATE_AND_TIME
+ [simple uint 8 unused]
+ [simple uint 8 seconds encoding='BCD']
+ [simple uint 8 minutes encoding='BCD']
+ [simple uint 8 hour encoding='BCD']
+ [simple uint 8 day encoding='BCD']
+ [simple uint 8 month encoding='BCD']
+ [simple uint 16 year encoding='BCD']
+ ]
]
]
-[enum uint 8 UmasDataType(uint 8 dataTypeSize, uint 8 requestSize)
- ['1' BOOL ['1','1']]
- ['2' UNKNOWN2 ['1','1']]
- ['3' UNKNOWN3 ['1','1']]
- ['4' INT ['2', '2']]
- ['5' UINT ['2','2']]
- ['6' DINT ['4','3']]
- ['7' UDINT ['4','3']]
- ['8' REAL ['4','3']]
- ['9' STRING ['1','17']]
- ['10' TIME ['4','3']]
- ['11' UNKNOWN11 ['1','1']]
- ['12' UNKNOWN12 ['1','1']]
- ['13' UNKNOWN13 ['1','1']]
- ['14' DATE ['4','3']]
- ['15' TOD ['4','3']]
- ['16' DT ['4','3']]
- ['17' UNKNOWN17 ['1','1']]
- ['18' UNKNOWN18 ['1','1']]
- ['19' UNKNOWN19 ['1','1']]
- ['20' UNKNOWN20 ['1','1']]
- ['21' BYTE ['1','1']]
- ['22' WORD ['2','2']]
- ['23' DWORD ['4','3']]
- ['24' UNKNOWN24 ['1','1']]
- ['25' EBOOL ['1','1']]
+[enum uint 8 UmasDataType(uint 8 dataTypeSize, uint 8 requestSize, vstring data_type_conversion )
+ ['1' BOOL ['1','1','"BOOL"']]
+ ['2' UNKNOWN2 ['1','1','"BOOL"']]
+ ['3' UNKNOWN3 ['1','1','"BOOL"']]
+ ['4' INT ['2', '2','"INT"']]
+ ['5' UINT ['2','2','"UINT"']]
+ ['6' DINT ['4','3','"DINT"']]
+ ['7' UDINT ['4','3','"UDINT"']]
+ ['8' REAL ['4','3','"REAL"']]
+ ['9' STRING ['1','17','"STRING"']]
+ ['10' TIME ['4','3','"TIME"']]
+ ['11' UNKNOWN11 ['1','1','"BYTE"']]
+ ['12' UNKNOWN12 ['1','1','"BYTE"']]
+ ['13' UNKNOWN13 ['1','1','"BYTE"']]
+ ['14' DATE ['4','3','"DATE"']]
+ ['15' TOD ['4','3','"TIME_OF_DAY"']]
+ ['16' DATE_AND_TIME ['8','4','"DATE_AND_TIME"']]
+ ['17' UNKNOWN17 ['1','1','"BYTE"']]
+ ['18' UNKNOWN18 ['1','1','"BYTE"']]
+ ['19' UNKNOWN19 ['1','1','"BYTE"']]
+ ['20' UNKNOWN20 ['1','1','"BYTE"']]
+ ['21' BYTE ['1','1','"BYTE"']]
+ ['22' WORD ['2','2','"WORD"']]
+ ['23' DWORD ['4','3','"DWORD"']]
+ ['24' UNKNOWN24 ['1','1','"BYTE"']]
+ ['25' EBOOL ['1','1','"BOOL"']]
]
[enum uint 8 ModbusErrorCode
diff --git a/src/site/asciidoc/apache/index.adoc b/src/site/asciidoc/apache/index.adoc
index 0f7364ccb11..35e48fafb3e 100644
--- a/src/site/asciidoc/apache/index.adoc
+++ b/src/site/asciidoc/apache/index.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../images/
:icons: font
-== Apache
+= Apache
diff --git a/src/site/asciidoc/developers/architecture.adoc b/src/site/asciidoc/developers/architecture.adoc
index 0e95ebf2013..784d26a3910 100644
--- a/src/site/asciidoc/developers/architecture.adoc
+++ b/src/site/asciidoc/developers/architecture.adoc
@@ -15,9 +15,9 @@
// limitations under the License.
//
-== Architecture of PLC4X Connections
+= Architecture of PLC4X Connections
-=== Simple case
+== Simple case
In this simple case, an application asks the DriverManager to forward a connection creation to the corresponding Driver implementation, which then creates both a Connection and a MessageCodec instance. The Connection is the logical link between the connection state and the MessageCodec.
A MessageCodec uses a TransportInstance to communicate with the target device.
@@ -84,13 +84,13 @@ note top of [Connection] : logical
....
-=== Problems
+== Problems
Serial transports based on RS475 and UDP Transports currently don't allow sharing. That means only one connection instance can have access to one RS485 or one shared local UDP Port (Multiple UDP transport instances with different local ports however are possible). As soon as one connection is established and a second connection would try to access this, this would result in errors.
However, multiple devices could be attached to the same RS458 port (Modbus RTU and Modbus ASCII explicitly supports this, however using different devices using different protocols over the same port is not possible) and in BACnet connecting to multiple remote BACnet devices would require one local UDP port to be used by multiple connections.
-=== Protocols requiring us to use a fixed port on a non-broadcast address
+== Protocols requiring us to use a fixed port on a non-broadcast address
Some protocols, such as BACnet require remotes to send data to a fixed udp port on a non-broadcast address. This causes problems as soon as we want to connect to multiple BACnet devices from the same host as only one instance can get access to that port.
@@ -157,6 +157,6 @@ note top of [Connection] : logical
....
-=== Protocols only allowing one connection at a time
+== Protocols only allowing one connection at a time
diff --git a/src/site/asciidoc/developers/building.adoc b/src/site/asciidoc/developers/building.adoc
index ce5aa78d50e..c2989fce7de 100644
--- a/src/site/asciidoc/developers/building.adoc
+++ b/src/site/asciidoc/developers/building.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Building PLC4X
+= Building PLC4X
PLC4X is built with `Apache Maven` and we have tried to make the build as simple as possible.
@@ -27,7 +27,7 @@ More about these later down in this manual.
For your convenience we also have provided a `Maven-Wrapper`, that should allow building of PLC4X with only `Java 11` or greater as requirement.
-=== Requirements
+== Requirements
The only requirements to building PLC4X should be:
@@ -35,7 +35,7 @@ The only requirements to building PLC4X should be:
* Git (Even if you are building the source distribution, the Kafka plugin seems to require a `git` executable being available on the systems `PATH`)
* Apache Maven (3.6.0 or newer) *(Optional)* (See next chapter)
-=== Using the Maven-Wrapper
+== Using the Maven-Wrapper
The so-called `Maven-Wrapper` is used by calling the Maven-Wrapper scripts `mvnw` (Mac & Linux) or `mvnw.cmd` (Windows) instead of the default Maven commands `mvn` and `mvn.cmd`.
@@ -45,7 +45,7 @@ If no suitable version can be found, it is automatically downloaded and installe
After the script has ensured a suitable Maven version is available, this is used and all arguments and parameters are transparently forwarded to this.
So simply adding the additional `w` to each of the Maven commands, there should be no difference to using a pre-installed Maven version.
-=== Using Maven
+== Using Maven
This document can't provide you with all the details needed to get started with `Maven` itself.
But there is a lot of good documentation out there.
@@ -57,7 +57,7 @@ It should handle all the details needed to get a general understanding of Maven
.Recording of a Maven Training for Apache Flex from 2016
https://vimeo.com/167857327
-=== Building PLC4X with Maven
+== Building PLC4X with Maven
As especially building the C++, and C# drivers requires building of some third party artifacts and increases build-time dramatically and requires setting up some additional third party tools, we have excluded these parts form the default Maven build.
@@ -95,7 +95,7 @@ If you want to skip the running of tests (even if this is not encouraged) you ca
This will not skip the compilation of tests, however.
-=== Building the PLC4X Website with Maven
+== Building the PLC4X Website with Maven
The PLC4X Website is also part of the same GIT repository that contains the code and it is built by Maven as well.
@@ -105,13 +105,13 @@ In order to build the website the following command should be sufficient:
This is just a quick-start version of the site generation, for a fully detailed documentation please read the https://plc4x.apache.org/developers/infrastructure/website.html[Website] documentation page.
-=== Some special Maven profiles
+== Some special Maven profiles
Maven supports so-called `profiles` for customizing the build in special cases.
We have tried to keep the number of profiles as low as possible.
So far there is only one profile.
-==== `apache-release` profile
+=== `apache-release` profile
This profile is automatically enabled on a release-build and it automatically creates some additional artifacts:
@@ -123,7 +123,7 @@ This profile is automatically enabled on a release-build and it automatically cr
Generally it is not required to enable ths profile unless you are interested in these Artifacts.
-==== `debug-pom` profile
+=== `debug-pom` profile
Especially for Maven beginners, it might be difficult to understand why a module builds the way it does.
Maven contains a lot of concepts to inherit and override settings.
@@ -141,7 +141,7 @@ Some tests of the PLC4X project do require quite a bit of time to run.
Therefore we decided to disable these for a normal build on developer machines.
If you want to run them locally and not rely on them being run on the CI servers, enable the `enable-all-checks` profile.
-=== Use the compiled library with Gradle
+== Use the compiled library with Gradle
Compiling the library as explained here add the new version in the local Maven repository (i.e. usually under `~/.m2/repository` on linux like systems), if you would like to use Gradle as Build Tool for your project you have just to use a local repository in your Gradle `build.gradle` file.
diff --git a/src/site/asciidoc/developers/code-gen/index.adoc b/src/site/asciidoc/developers/code-gen/index.adoc
index 83019d265f4..5c0f3b96e48 100644
--- a/src/site/asciidoc/developers/code-gen/index.adoc
+++ b/src/site/asciidoc/developers/code-gen/index.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../../images/
-== Code Generation
+= Code Generation
As hand-writing code for a lot of drivers in multiple languages would be quite a nightmare, we have invested a very large amount of time into finding a way to automate this.
@@ -120,7 +120,7 @@ So for example in case of generating a `Siemens S7` Driver for `Java` this would
The dark blue parts are the ones released externally, the turquoise ones are part of the main PLC4X repo.
-=== Introduction
+== Introduction
The maven plugin is built up very modular.
@@ -141,7 +141,7 @@ The downside was, that the PLC4X community regarded this XML format as pretty co
In the end we came up with our own format which we called `MSpec` and is described in the link:protocol/mspec.html[MSpec Format description].
-=== Configuration
+== Configuration
The `plc4x-maven-plugin` has a very limited set of configuration options.
@@ -295,11 +295,11 @@ and:
The reason for why the dependencies are added as code-dependencies and why the scope is set the way it is, is described in the <> section.
-=== Custom Modules
+== Custom Modules
The plugin uses the https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html[Java Serviceloader] mechanism to find modules.
-==== Protocol Modules
+=== Protocol Modules
In order to provide a new protocol module, all that is required, it so create a module containing a `META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol` file referencing an implementation of the `org.apache.plc4x.plugins.codegenerator.protocol.Protocol` interface.
@@ -346,7 +346,7 @@ As mentioned before, we support multiple versions of a protocol, so if `getVersi
The most important method for the actual code-generation however is the `getTypeContext()` method, which returns a `TypeContext` type which generally contains a list of all parsed types for this given protocol.
-==== Language Modules
+=== Language Modules
Analog to the <> the Language modules are constructed very similar.
@@ -394,9 +394,9 @@ The `name` being used by the plugin to find the language output module defined b
`supportedOptions` provides a list of `options` that the current language module is able to use and which can be passed in to the maven configuration using the `options` settings.
-=== Problems with Maven
+== Problems with Maven
-==== Why are the 4 modules released separately?
+=== Why are the 4 modules released separately?
We mentioned in the introduction, that the first 4 modules are maintained and released from outside the main PLC4X repository.
@@ -417,7 +417,7 @@ For this reason we have stripped down the plugin and its dependencies to an abso
As soon as the tooling is released, the version is updated in the PLC4X build and the release version is used without any complications.
-==== Why are the protocol and language dependencies done so strangely?
+=== Why are the protocol and language dependencies done so strangely?
It would certainly be a lot cleaner, if we provided the dependencies to protocol and language modules as plugin dependencies.
diff --git a/src/site/asciidoc/developers/code-gen/language/freemarker.adoc b/src/site/asciidoc/developers/code-gen/language/freemarker.adoc
index 5c53337b8f5..5851fcff0b0 100644
--- a/src/site/asciidoc/developers/code-gen/language/freemarker.adoc
+++ b/src/site/asciidoc/developers/code-gen/language/freemarker.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../../../images/
-== Apache Freemarker
+= Apache Freemarker
For the Freemarker language output we are using an unmodified version of https://freemarker.apache.org[Apache Freemarker] to generate output.
@@ -48,7 +48,7 @@ It will automatically create all needed intermediate directories and generate th
If this line is empty, the output is skipped for this type.
-=== Example `Java` output
+== Example `Java` output
....
package org.apache.plc4x.language.java;
diff --git a/src/site/asciidoc/developers/code-gen/protocol/df1.adoc b/src/site/asciidoc/developers/code-gen/protocol/df1.adoc
index ca52ae1738a..aba67938037 100644
--- a/src/site/asciidoc/developers/code-gen/protocol/df1.adoc
+++ b/src/site/asciidoc/developers/code-gen/protocol/df1.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Example: DF1 MSpec
+= Example: DF1 MSpec
The DF1 protocol has three basic messages: a command message, acknowledge and not acknowledge.
A `0x10` is used as delimiter to differentiate between the messages and parts of the command message.
diff --git a/src/site/asciidoc/developers/code-gen/protocol/mspec.adoc b/src/site/asciidoc/developers/code-gen/protocol/mspec.adoc
index 8d19b56480e..c8b20a35e31 100644
--- a/src/site/asciidoc/developers/code-gen/protocol/mspec.adoc
+++ b/src/site/asciidoc/developers/code-gen/protocol/mspec.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../../../images/
-== The MSpec format
+= The MSpec format
The `MSpec` format (Message Specification) was a result of a brainstorming session after evaluating a lot of other options.
@@ -109,7 +109,7 @@ In general, we distinguish between two types of types used in field definitions:
- simple types
- complex types
-=== Simple Types
+== Simple Types
Simple types are usually raw data the format is:
@@ -138,7 +138,7 @@ There is currently one special type, reserved for string values, whose length is
- *vstring*: The input is treated as a variable length string and requires an expression tp provide the number of bits to read.
-=== Complex Types
+== Complex Types
In contrast to simple types, complex types reference other complex types (Root elements of the spec document).
@@ -146,9 +146,9 @@ How the parser should interpret them is defined in the referenced types definiti
In the example above, for example the `S7Parameter` is defined in another part of the spec.
-=== Field Types and their Syntax
+== Field Types and their Syntax
-==== array Field
+=== array Field
An `array` field is exactly what you expect.
It generates an field which is not a single-value element but an array or list of elements.
@@ -166,7 +166,7 @@ Possible values are:
- `length`: In this case a given number of bytes are being read. So if an element has been parsed and there are still bytes left, another element is parsed.
- `terminated`: In this case the parser will continue reading elements until it encounters a termination sequence.
-==== assert Field
+=== assert Field
An assert field is pretty much identical to a `const` field.
The main difference however it how the case is handled, if the parsed value does not match the expected value.
@@ -185,7 +185,7 @@ See also:
- validation field: Similar to an `assert` field, however no parsing is done, and instead simply a condition is checked.
- optional field: `optional` fields are aware of the types of parser errors produced by `assert` and `validation` fields
-==== checksum Field
+=== checksum Field
A checksum field can only operate on simple types.
@@ -205,7 +205,7 @@ This field doesn't keep any data in memory.
See also:
- implicit field: A checksum field is similar to an implicit field, however the `checksum-expression` is evaluated are parsing time and throws an exception if the values don't match.
-==== const Field
+=== const Field
A const field simply reads a given simple type and compares to a given reference value.
@@ -222,7 +222,7 @@ This field doesn't keep any data in memory.
See also:
- implicit field: A const field is similar to an implicit field, however it compares the parsed input to the reference value and throws an exception if the values don't match.
-==== discriminator Field
+=== discriminator Field
Discriminator fields are only used in `discriminatedType`s.
@@ -239,7 +239,7 @@ See also:
- implicit field: A discriminator field is similar to an implicit field, however doesn't provide a serialization expression as it uses the discrimination constants of the type it is.
- discriminated types
-==== implicit Field
+=== implicit Field
Implicit types are fields that get their value implicitly from the data they contain.
@@ -255,7 +255,7 @@ This type of field is generally used for fields that handle numbers of elements
This field doesn't keep any data in memory.
-==== manualArray Field
+=== manualArray Field
[manualArray {bit|byte} {name} {count|length|terminated} '{loop-expression}' '{serialization-expression}' '{deserialization-expression}' '{length-expression}']
@@ -263,7 +263,7 @@ This field doesn't keep any data in memory.
[manualArray {complex-type} {name} {count|length|terminated} '{loop-expression}' '{serialization-expression}' '{deserialization-expression}' '{length-expression}']
-==== manual Field
+=== manual Field
[manual {bit|byte} {name} '{serialization-expression}' '{deserialization-expression}' '{length-expression}']
@@ -271,7 +271,7 @@ This field doesn't keep any data in memory.
[manual {complex-type} {name} '{serialization-expression}' '{deserialization-expression}' '{length-expression}']
-==== optional Field
+=== optional Field
An optional field is a type of field that can also be `null`.
@@ -293,7 +293,7 @@ See also:
- `assert`: Assert fields are similar to `const` fields, but can abort parsing of an `optional` filed.
- `validation`: If a validation field in any of the subtypes fails, this aborts parsing of the `optional` field.
-==== padding Field
+=== padding Field
A padding field allows aligning of data blocks.
It outputs additional padding data, given amount of times specified by padding expression.
@@ -309,11 +309,11 @@ When serializing, the `times-padding` defines how often the `padding-value` shou
This field doesn't keep any data in memory.
-===== peek Field
+==== peek Field
// TODO: Implement
-==== reserved Field
+=== reserved Field
Reserved fields are very similar to `const` fields, however they don't throw exceptions, but instead log messages if the values don't match.
@@ -334,7 +334,7 @@ This field doesn't keep any data in memory.
See also:
- `const` field
-==== simple Field
+=== simple Field
Simple fields are the most common types of fields.
@@ -350,7 +350,7 @@ When parsing, the given type is parsed (can't be `null`) and saved in the corres
When serializing it is serialized normally using either a simple type serializer or by delegating serialization to a complex type.
-==== typeSwitch Field
+=== typeSwitch Field
// TODO: Finish this ...
@@ -393,7 +393,7 @@ These arguments are then available for expressions or passing on in the subtypes
See also:
- `discriminatedType`
-===== unknown Field
+==== unknown Field
// TODO: Finish this ...
@@ -402,7 +402,7 @@ It allows parsing any type of information, storing and using it and serializing
In general, it's something similar to a `simple` field, just explicitly states, that we don't yet quite know how to handle the content.
-===== validation Field
+==== validation Field
As mentioned before, a `validation` field is not really a field, it's a check that is added to the type parser.
@@ -414,7 +414,7 @@ If it finds one, it rewinds the parser to the position just before starting to p
If there is no `optional` field up the stack, then parsing fails.
-==== virtual Field
+=== virtual Field
Virtual fields have no impact on the input or output.
They simply result in creating artificial get-methods in the generated model classes.
@@ -427,7 +427,7 @@ They simply result in creating artificial get-methods in the generated model cla
Instead of being bound to a property, the return value of a `virtual` property is created by evaluating the `value-expression`.
-==== Parameters
+=== Parameters
Sometimes it is necessary to pass along additional parameters.
@@ -459,13 +459,13 @@ Here comes an example of this in above snippet:
[field S7Payload 'payload' ['messageType', 'parameter']]
-==== Serializer and Parser-Arguments
+=== Serializer and Parser-Arguments
Arguments influence the way the parser or serializer operates.
Wherever an parser-argument is used, this should also be valid in all subtypes the parser processes.
-===== byteOrder
+==== byteOrder
A `byteOrder` argument can set or change the byte-order used by the parser.
@@ -474,7 +474,7 @@ We currently support two variants:
- BIG_ENDIAN
- LITTLE_ENDIAN
-===== encoding
+==== encoding
Each simple type has a default encoding, which is ok for a very high percentage of cases.
diff --git a/src/site/asciidoc/developers/conferences.adoc b/src/site/asciidoc/developers/conferences.adoc
index cde6fe09367..4be49a499bf 100644
--- a/src/site/asciidoc/developers/conferences.adoc
+++ b/src/site/asciidoc/developers/conferences.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Conferences & Events
+= Conferences & Events
On this page we are listing options to attend talks and events around PLC4X.
diff --git a/src/site/asciidoc/developers/contributing.adoc b/src/site/asciidoc/developers/contributing.adoc
index 09fc6a60cf2..368f9517722 100644
--- a/src/site/asciidoc/developers/contributing.adoc
+++ b/src/site/asciidoc/developers/contributing.adoc
@@ -16,9 +16,9 @@
//
:imagesdir: ../images/
-== Contributing
+= Contributing
-=== Forms of contribution
+== Forms of contribution
There are multiple forms in which you can become involved with the PLC4X project.
@@ -32,13 +32,13 @@ These usually are, but are not limited to:
We are a very friendly bunch and don't be afraid to step forward.
-=== Commits
+== Commits
We make use of https://www.conventionalcommits.org/en/v1.0.0/[conventional commits].
As plc4x is a monolithic polyglot repository we usually define the scope as `...(plc4[language shortcut here]/subcomponent)`
(e.g. a new feature in Bacnet in the Golang part would have a message of `feat(plc4go/bacnet): cool new feature for...`).
-=== Pull-Requests
+== Pull-Requests
The simplest way to submit code changes, is via a GitHub pull-request.
@@ -67,7 +67,7 @@ image::contributing-github-create-pull-request.png[]
If you click on this, we will receive a notification on your changes and can review them.
We also can discuss your changes and have you perfect your pull request before we accept and merge it into PLC4X.
-==== Keeping your fork up to date
+=== Keeping your fork up to date
As we are continuously working on PLC4X and you created a copy of our repo, this will become out-of-date pretty soon.
@@ -106,7 +106,7 @@ You can do this by executing the following command:
(If no remote is provided, git will use `origin` per default)
-=== Bug Reports
+=== Bug Reports
We use https://issues.apache.org/jira/projects/PLC4X[JIRA] as our Bug & Issue Tracker.
@@ -120,14 +120,14 @@ So if you are considering to contribute more than just a one-time-patch, please
If you want to be assigned to an issue because you want to work on it, please request to be added to the JIRA groups on our http://plc4x.apache.org/mailing-lists.html[developers mailing list]
-=== Documentation
+== Documentation
As our documentation and website are generated as a side-product of our build, contributing to this technically the same as contributing to the code.
All our content is written in Asciidoctor and is located in `src/site/asciidoc` directories.
For a reference of the Asciidoctor syntax please have a look at the https://asciidoctor.org/docs/user-manual/#introduction-to-asciidoctor[Asciidoctor documentation].
-=== Branching model
+== Branching model
The PLC4X project uses the following branching model.
diff --git a/src/site/asciidoc/developers/decisions.adoc b/src/site/asciidoc/developers/decisions.adoc
index 61d181e9282..f4d43e2e7d0 100644
--- a/src/site/asciidoc/developers/decisions.adoc
+++ b/src/site/asciidoc/developers/decisions.adoc
@@ -16,9 +16,9 @@
//
:imagesdir: ../images/
-== Decision Making
+= Decision Making
-=== Introduction
+== Introduction
This document describes the roles and responsibilities of the project, who may vote, how voting works, how conflicts are resolved, etc.
@@ -26,19 +26,19 @@ The https://www.apache.org/foundation/faq[Apache Foundation FAQ] and http://www.
Apache has a http://www.apache.org/foundation/policies/conduct.html[code of conduct] that it expects its members to follow.
-=== Roles and Responsibilities
+== Roles and Responsibilities
Apache projects define a set of https://www.apache.org/foundation/how-it-works.html#roles[roles] with associated rights and responsibilities.
-==== Project Management Committee
+=== Project Management Committee
The http://www.apache.org/dev/pmc.html#what-is-a-pmc[PMC] has many https://www.apache.org/foundation/how-it-works.html#pmc[responsibilities] including complying with http://www.apache.org/dev/pmc.html#policy[ASF policies], https://www.apache.org/foundation/board/reporting[reporting to the board], https://www.apache.org/foundation/voting.html[approving releases] and adding new http://www.apache.org/dev/pmc.html#newcommitter[committers] and http://www.apache.org/dev/pmc.html#newpmc[PMC members].
-==== The Chair
+=== The Chair
The http://www.apache.org/dev/pmc.html#chair[chair] ensures board reports are submitted and that the project's roster is up to date.
-=== Decision Making
+== Decision Making
Different decisions require different forms of approval but community consensus is always the goal. Voting when needed should be open for http://www.apache.org/legal/release-policy.html#release-approval[at least 72 hours].
diff --git a/src/site/asciidoc/developers/index.adoc b/src/site/asciidoc/developers/index.adoc
index 33aea916a25..43540280f4f 100644
--- a/src/site/asciidoc/developers/index.adoc
+++ b/src/site/asciidoc/developers/index.adoc
@@ -17,11 +17,11 @@
:imagesdir: ../images/
:icons: font
-== Developer Section
+= Developer Section
This part of the Apache PLC4X dedicated to provide information to people wanting to build PLC4X and hopefully also start contributing to this awesome project.
-=== Getting Started
+== Getting Started
We have tried to make the PLC4X build experience as smooth as possible and have tried to reduce the number of required third party tools to an absolute minimum.
@@ -35,17 +35,17 @@ As part of the build we have an initial build step that will do a `prerequisite
For details please have a look at the link:preparing/index.html[Preparing your Computer] page.
-=== Building PLC4X
+== Building PLC4X
We have a dedicated page on link:building.html[Building PLC4X].
Please read this page on information about how to build Apache PLC4X.
-=== Contributing
+== Contributing
If you want to work on Apache PLC4X in order to `fix things`, `add things` and start `contributing` in general, please have a look at our link:contributing.html[Contributing] page. It should contain all the information you need.
-=== Getting Help
+== Getting Help
The primary source for getting help definitely is our project mailing list dev@plc4x.apache.org.
diff --git a/src/site/asciidoc/developers/infrastructure/ci.adoc b/src/site/asciidoc/developers/infrastructure/ci.adoc
index fcb0558cf64..0c72f6c87bf 100644
--- a/src/site/asciidoc/developers/infrastructure/ci.adoc
+++ b/src/site/asciidoc/developers/infrastructure/ci.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../images/
-== Continuous Integration
+= Continuous Integration
We are currently using the following CI systems.
@@ -30,7 +30,7 @@ GitHub Actions on the other side responsible for doing the main part of the test
It not only builds and runs the tests on a matrix of operating systems as well as with a number of java versions.
It also is configured to run the tests on pull-requests.
-=== Structure of the Jenkins Pipeline build
+== Structure of the Jenkins Pipeline build
We are using the Jenkins `multi-branch pipeline plugin` to automatically setup build for branches based upon the build definition in the `Jenkinsfile` in the root of the project.
diff --git a/src/site/asciidoc/developers/infrastructure/index.adoc b/src/site/asciidoc/developers/infrastructure/index.adoc
index 7f48619a72b..fd9b4a41698 100644
--- a/src/site/asciidoc/developers/infrastructure/index.adoc
+++ b/src/site/asciidoc/developers/infrastructure/index.adoc
@@ -17,6 +17,6 @@
:imagesdir: ../../images/
:icons: font
-== Infrastructure
+= Infrastructure
In this section you can find information on the services the Apache PLC4X project makes use of.
diff --git a/src/site/asciidoc/developers/infrastructure/issues.adoc b/src/site/asciidoc/developers/infrastructure/issues.adoc
index 13b44a1f377..1000e363e31 100644
--- a/src/site/asciidoc/developers/infrastructure/issues.adoc
+++ b/src/site/asciidoc/developers/infrastructure/issues.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Bug & Issue Tracker
+= Bug & Issue Tracker
Our bug & issue tracker is Github-Issues.
diff --git a/src/site/asciidoc/developers/infrastructure/sonar.adoc b/src/site/asciidoc/developers/infrastructure/sonar.adoc
index 663d9199e6d..eae01fc9ca6 100644
--- a/src/site/asciidoc/developers/infrastructure/sonar.adoc
+++ b/src/site/asciidoc/developers/infrastructure/sonar.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Code Analysis
+= Code Analysis
We are using `SonarCloud` as the service for static code analysis.
diff --git a/src/site/asciidoc/developers/infrastructure/vm.adoc b/src/site/asciidoc/developers/infrastructure/vm.adoc
index a42a8d8b705..4bce1f2358d 100644
--- a/src/site/asciidoc/developers/infrastructure/vm.adoc
+++ b/src/site/asciidoc/developers/infrastructure/vm.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== The PLC4X Project VM
+= The PLC4X Project VM
As, especially for the raw socket functionality of PLC4X, our project had higher demands on the infrastructure as other projects.
Apache Infra kindly provided us with a dedicated VM.
@@ -28,7 +28,7 @@ On this machine we can even `sudo` to perform operations only available to `root
Project members can request access to the machine.
-=== Requesting access
+== Requesting access
In order to be able to log in, users need to add their SSH public key to their Apache ID first.
@@ -50,7 +50,7 @@ Here make sure to select the Project `Infrastructure (INFRA)`.
As soon as that's handled by the Infra team, you should be ready to log-in on the machine.
-=== Login to the machine
+== Login to the machine
Using SSH we should now be able to log in to the VM.
@@ -60,7 +60,7 @@ Be sure to use the username matching your Apache ID or the login will fail.
If all went well you should now be able to log in to the machine using your apache user.
-=== Doing things as `root`
+== Doing things as `root`
Apache Infra is great at keeping things safe.
Providing a sudo password directly would increase the danger of having this intercepted, therefore they are using a tool called `opiepasswd`.
@@ -94,7 +94,7 @@ https://selfserve.apache.org/otp-calculator.html
TIP: More help can be found for Apache committers at https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=122916896
-=== Required software
+== Required software
For being able to build the charts and graphics as part of the site generation, we need to add some additional packages:
diff --git a/src/site/asciidoc/developers/infrastructure/website.adoc b/src/site/asciidoc/developers/infrastructure/website.adoc
index 5a390688d91..d53c7b3c89a 100644
--- a/src/site/asciidoc/developers/infrastructure/website.adoc
+++ b/src/site/asciidoc/developers/infrastructure/website.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Generating the Website
+= Generating the Website
We are currently using the normal `Maven` build to not only generate the project artifacts, but also the projects website.
@@ -36,7 +36,7 @@ Beyond the basic goodies, the build is also configured to generate images from A
This allows us to generate images like the ones on the http://plc4x.apache.org/protocols/s7/index.html[S7 Protocol Description page]
-=== Providing new content
+== Providing new content
Within the `src/site` directory there is a file `site.xml` which generally controls the menu and the look of the site.
@@ -51,7 +51,7 @@ So if we wanted to add a new page on some (hopefully non existent) `Wombat PLC P
For example with this content:
```
-== Wombat PLC Protocol
+= Wombat PLC Protocol
If you want to waste your money, brains and time, feel free to use a `Wombat PLC`.
@@ -75,7 +75,7 @@ After the build, you would find a file `target/site/protocols/wombat/index.html`
However you can link to this page from any other page, but it is not added ot the navigation menu.
-=== Adding links to menus
+== Adding links to menus
In order to add links to the menus, you have to create or modify the `site.xml` for the module you want to add content to.
@@ -158,7 +158,7 @@ If you want to insert the menu somewhere else, you will have to re-define the en
The `menu ref` items hereby reference standard menus provided by the `Maven` build.
-=== Deploying the Website
+== Deploying the Website
The PLC4X project uses Apache `gitpubsub` system for maintaining the website.
diff --git a/src/site/asciidoc/developers/infrastructure/wiki.adoc b/src/site/asciidoc/developers/infrastructure/wiki.adoc
index 7c72a1c894c..6afbb897e11 100644
--- a/src/site/asciidoc/developers/infrastructure/wiki.adoc
+++ b/src/site/asciidoc/developers/infrastructure/wiki.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== WIKI
+= WIKI
We use Apache's Confluence instance as Wiki, however most information is generally managed on this website.
diff --git a/src/site/asciidoc/developers/jqassistant.adoc b/src/site/asciidoc/developers/jqassistant.adoc
index edd69283fa7..dd924860ba7 100644
--- a/src/site/asciidoc/developers/jqassistant.adoc
+++ b/src/site/asciidoc/developers/jqassistant.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../images/
-== Using JQAssistant
+= Using JQAssistant
In PLC4X we are using a tool called `https://jqassistant.org/[JQAssistant]` for enforcing quality assurance rules.
@@ -58,11 +58,11 @@ These rules that are automatically checked during the build are defined in `src/
If defined in a reactor project, the rules apply to all modules of that (sub-)reactor.
So if they are defined in the root module of the project, it applies to all modules.
-=== Defining JQAssistant rules
+== Defining JQAssistant rules
TODO: Finish this "little detail" ...
-=== Using the Web-UI
+== Using the Web-UI
The scan and analysis is automatically performed during a normal Maven build.
In order to do ad-hoc queries against the project or develop new rules, the Web-UI is very helpful.
@@ -93,7 +93,7 @@ So when visiting the anounced url with a browser, you can use the pretty useful
image::neo4j-web-console.png[Neo4j Web Console]
-=== Using IntelliJ Idea
+== Using IntelliJ Idea
IntelliJ comes with some interesting Neo4J support. Unfortunately this only supports `Neo4j 3`.
diff --git a/src/site/asciidoc/developers/maturity.adoc b/src/site/asciidoc/developers/maturity.adoc
index dbefed507ae..3cf0bc87508 100644
--- a/src/site/asciidoc/developers/maturity.adoc
+++ b/src/site/asciidoc/developers/maturity.adoc
@@ -17,15 +17,15 @@
:icons: font
-== Apache Maturity Model Assessment for PLC4X
+= Apache Maturity Model Assessment for PLC4X
-=== Overview
+== Overview
This is an assessment of the PLC4X project's maturity, meant to help inform the decision (of the mentors, community, Incubator PMC and ASF Board of Directors) to graduate it as a top-level Apache project.
It is based on the ASF project maturity model at https://community.apache.org/apache-way/apache-project-maturity-model.html
-=== Maturity model assessment
+== Maturity model assessment
Community members are encouraged to contribute to this page and comment on it, the following table summarizes project’s self-assessment against the Apache Maturity Model.
diff --git a/src/site/asciidoc/developers/preparing/index.adoc b/src/site/asciidoc/developers/preparing/index.adoc
index 460f2affa7f..98d8475b513 100644
--- a/src/site/asciidoc/developers/preparing/index.adoc
+++ b/src/site/asciidoc/developers/preparing/index.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Preparing your Computer
+= Preparing your Computer
Building a project like Apache PLC4X on multiple target operating-systems is quite a challenge, but I think we managed to make it as simple as possible.
diff --git a/src/site/asciidoc/developers/preparing/linux.adoc b/src/site/asciidoc/developers/preparing/linux.adoc
index 84925717534..fb08eb59a4a 100644
--- a/src/site/asciidoc/developers/preparing/linux.adoc
+++ b/src/site/asciidoc/developers/preparing/linux.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Linux
+= Linux
As tracking down issues which result from missing or outdated third party tools such as compilers are always hard do diagnose, we have extended the build of PLC4X with a `prerequisiteCheck` that automatically checks if required tools are installed and if a required minimum version is available.
@@ -26,7 +26,7 @@ So for example the availability and version of the C compiler is only checked if
If the check is reporting any issues, please feel free to follow the corresponding steps in this guide to install the tools.
-=== Git
+== Git
Checking:
@@ -42,7 +42,7 @@ Yum based systems:
sudo yum install git
-=== Java
+== Java
Checking:
@@ -54,11 +54,11 @@ Apt based systems:
sudo apt install openjdk-21-jdk
-=== Optional and other language support
+== Optional and other language support
Git an Java should be all you need for building the Java part of PLC4X.
-==== LibPCAP (For raw-ethernet support)
+=== LibPCAP (For raw-ethernet support)
Apt-based systems:
@@ -81,7 +81,7 @@ Sometimes I had to set the uid to execute the java executable with the permissio
sudo chmod 4755 /path/to/java
-==== gcc (For PLC4C)
+=== gcc (For PLC4C)
NOTE: It seems that when running Linux on `aarch64` (Apple's Silicon Chips), that there are issues ... we're working on that. Feel free to watch https://github.com/apache/plc4x/issues/1582 on updates to this.
@@ -99,7 +99,7 @@ Yum based systems:
sudo yum install gcc
-==== dotnet (For PLC4Net)
+=== dotnet (For PLC4Net)
Checking:
@@ -125,7 +125,7 @@ If, when checking the version again after installing, you are getting an error:
Then please have a look at this Stackoverflow post (the accepted solution) https://stackoverflow.com/questions/73753672/a-fatal-error-occurred-the-folder-usr-share-dotnet-host-fxr-does-not-exist
-==== python (For PLC4Py)
+=== python (For PLC4Py)
Checking:
@@ -141,7 +141,7 @@ Yum based systems:
yum intall python3
-==== Python venv (For PLC4Py)
+=== Python venv (For PLC4Py)
Checking:
diff --git a/src/site/asciidoc/developers/preparing/macos.adoc b/src/site/asciidoc/developers/preparing/macos.adoc
index d61bc261981..289030dced6 100644
--- a/src/site/asciidoc/developers/preparing/macos.adoc
+++ b/src/site/asciidoc/developers/preparing/macos.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Mac OS
+= Mac OS
As tracking down issues which result from missing or outdated third party tools such as compilers are always hard do diagnose, we have extended the build of PLC4X with a `prerequisiteCheck` that automatically checks if required tools are installed and if a required minimum version is available.
@@ -30,7 +30,7 @@ Make sure `Homebrew` ist installed in order to install most of these.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
-=== Git
+== Git
Checking:
@@ -45,7 +45,7 @@ If you get a response that indicates that git needs to be installed, please exec
brew install git
-=== Java
+== Java
Checking:
@@ -57,11 +57,11 @@ Apt based systems:
brew install openjdk
-=== Optional and other language support
+== Optional and other language support
Git an Java should be all you need for building the Java part of PLC4X.
-==== LibPCAP (For raw-ethernet support)
+=== LibPCAP (For raw-ethernet support)
The libpcap version bundled with macOS is currently 1.9.1.
This version causes exceptions.
@@ -69,7 +69,7 @@ So it's best to update to a newer version using brew:
brew install libpcap
-==== gcc (For PLC4C)
+=== gcc (For PLC4C)
Checking:
@@ -79,7 +79,7 @@ If you get any successful output, you probably don't need to do anything.
It seems macOS comes with a version of gcc which is good enough for our use cases.
-==== dotnet (For PLC4Net)
+=== dotnet (For PLC4Net)
Checking:
@@ -93,7 +93,7 @@ Alternatively you can also install it via homebrew:
brew install --cask dotnet-sdk
-==== python (For PLC4Py)
+=== python (For PLC4Py)
Checking:
diff --git a/src/site/asciidoc/developers/preparing/windows.adoc b/src/site/asciidoc/developers/preparing/windows.adoc
index f602b1cc589..8b1b1164abf 100644
--- a/src/site/asciidoc/developers/preparing/windows.adoc
+++ b/src/site/asciidoc/developers/preparing/windows.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Windows
+= Windows
As tracking down issues which result from missing or outdated third party tools such as compilers are always hard do diagnose, we have extended the build of PLC4X with a `prerequisiteCheck` that automatically checks if required tools are installed and if a required minimum version is available.
@@ -28,7 +28,7 @@ As in the past keeping the documentation up to date has been quite challenging,
So first be sure to install Chocolatey from here: https://community.chocolatey.org/ and follow the most recent instructions on that page in order to install it.
-=== Git
+== Git
Checking:
@@ -40,7 +40,7 @@ If above command is not successful, simply install it via Chocolatey:
choco install git
-=== Java
+== Java
Checking:
@@ -52,11 +52,11 @@ If you need to install or update Java, unfortunately this doesn't seem to be ava
For Oracles OpenJDK 21 this would be from here: https://learn.microsoft.com/de-de/java/openjdk/download
If you are using a Windows VM on `aarch64` (Apple M1 or M2 virtual machine), the download available from Microsoft build seem to be one of the few options you have. When installing make sure to select the option to configure the "JAVA_HOME" environment variable (deactivated per default).
-=== Optional and other language support
+== Optional and other language support
Git an Java should be all you need for building the Java part of PLC4X.
-==== LibPCAP (For raw-ethernet support)
+=== LibPCAP (For raw-ethernet support)
In order to use the raw ethernet transport capabilities of PLC4X, we need to ensure the NPcap library is installed.
@@ -74,7 +74,7 @@ In order to check if NPcap is installed, check the following directories:
If none of these can be found, install it by downloading the installer from https://npcap.com/#download
-==== gcc (For PLC4C)
+=== gcc (For PLC4C)
Checking:
@@ -92,7 +92,7 @@ https://repo.maven.apache.org/maven2/com/googlecode/cmake-maven-project/cmake-bi
Deploy as:
https://repo.maven.apache.org/maven2/com/googlecode/cmake-maven-project/cmake-binaries/3.27.7-b1/cmake-binaries-3.27.7-b1-windows-arm64.jar
-==== dotnet (For PLC4Net)
+=== dotnet (For PLC4Net)
Checking:
@@ -104,7 +104,7 @@ Usually this is already installed on Windows machines.
Download the installer from https://dotnet.microsoft.com/en-us/download[here]
-==== python (For PLC4Py)
+=== python (For PLC4Py)
Checking:
diff --git a/src/site/asciidoc/developers/protocols/ads/protocol.adoc b/src/site/asciidoc/developers/protocols/ads/protocol.adoc
index d71aa790360..79d9e73c1ee 100644
--- a/src/site/asciidoc/developers/protocols/ads/protocol.adoc
+++ b/src/site/asciidoc/developers/protocols/ads/protocol.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Beckhoff ADS Protocol
+= Beckhoff ADS Protocol
// https://plantuml.com/de/activity-diagram-legacy
// https://deepu.js.org/svg-seq-diagram/Reference_Guide.pdf
diff --git a/src/site/asciidoc/developers/protocols/eip/protocol.adoc b/src/site/asciidoc/developers/protocols/eip/protocol.adoc
index 1cf6bbbc4c3..ddf2120ae31 100644
--- a/src/site/asciidoc/developers/protocols/eip/protocol.adoc
+++ b/src/site/asciidoc/developers/protocols/eip/protocol.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== EIP Protocol
+= EIP Protocol
// https://plantuml.com/de/activity-diagram-legacy
// https://deepu.js.org/svg-seq-diagram/Reference_Guide.pdf
diff --git a/src/site/asciidoc/developers/protocols/index.adoc b/src/site/asciidoc/developers/protocols/index.adoc
index c3aa351f8bb..c0b0b010b01 100644
--- a/src/site/asciidoc/developers/protocols/index.adoc
+++ b/src/site/asciidoc/developers/protocols/index.adoc
@@ -15,9 +15,9 @@
// limitations under the License.
//
-== Usage of protocols
+= Usage of protocols
-=== Currently documented are:
+== Currently documented are:
- link:ads/protocol.html[Beckhoff/ ADS]
- link:eip/protocol.html[EIP]
diff --git a/src/site/asciidoc/developers/release/build-tools.adoc b/src/site/asciidoc/developers/release/build-tools.adoc
index 4375c95ca2c..f865ee51f64 100644
--- a/src/site/asciidoc/developers/release/build-tools.adoc
+++ b/src/site/asciidoc/developers/release/build-tools.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Releasing PLC4X Build-Tools
+= Releasing PLC4X Build-Tools
In contrast to the main project, the `plc4x-build-tools` repository contains a loose collection of sub-projects.
@@ -30,7 +30,7 @@ So please check link:release.html[here] (Chapters: `Preparing your system for be
The rest of the steps are a lot simpler than those of the main project as there aren't any profiles involved.
-=== Creating a release branch (For the code-generation module)
+== Creating a release branch (For the code-generation module)
According to SemVer, we have: Major, Minor and Bugfix releases.
@@ -68,7 +68,7 @@ This step now should perform quite quickly as no build and no tests are involved
However in the end the versions of the `develop` branch are updated and a new `releases/code-generation/{code-generation-short-version}` branch is created.
-=== Preparing `develop` for the next iteration
+== Preparing `develop` for the next iteration
Now is a good time to add a new section to the `RELEASE_NOTES` document for the new `SNAPSHOT` version.
@@ -99,7 +99,7 @@ Also be sure to do a quick full-text-search to check if the version was updated
WARNING: If you find anything here, you will need to pay attention during the release.
-=== Release stabilization phase
+== Release stabilization phase
Now usually comes a phase in which last tests and checks should be performed.
@@ -107,7 +107,7 @@ If any problems are found they, have to be fixed in the release branch.
Changes should either be re applied in `develop` or `cherry-picked`, however merging things back can cause a lot of problems, and we no longer have the same versions.
-=== Preparing a release
+== Preparing a release
Before you start preparing the release, it is important to manually make the `RELEASE_NOTES` reflect the version we are planning on releasing.
@@ -180,7 +180,7 @@ And it will change the versions back and commit and push things.
However, it will not delete the tag in GIT (locally and remotely). So you have to do that manually or use a different tag next time.
-=== Performing a release
+== Performing a release
This is done by executing another goal of the `maven-release-plugin`:
@@ -217,7 +217,7 @@ This contains all sources of the project and will be what's actually the release
This file will also be signed and `SHA512` hashes will be created.
-=== Staging a release
+== Staging a release
Each new release and release-candidate has to be staged in the Apache SVN under:
@@ -257,7 +257,7 @@ The three `*-source-release.zip*` artifacts should be located in the directory:
So, after committing these files to SVN, you are ready to start the vote.
-=== Starting a vote on the mailing list
+== Starting a vote on the mailing list
After staging the release candidate in the Apache SVN, it is time to actually call out the vote.
@@ -335,7 +335,7 @@ After the 72-our minimum wait period is over, and we have fulfilled the requirem
Chris
----
-=== Releasing after a successful vote
+== Releasing after a successful vote
As soon as the votes are finished, and the results were in favor of a release, the staged artifacts can be released.
This is done by moving them inside the Apache SVN.
@@ -351,7 +351,7 @@ This will make the release artifacts available and will trigger them being copie
This is also the reason why you should wait at least 24 hours before sending out the release notification emails.
-=== Cleaning up older release versions
+== Cleaning up older release versions
As a lot of mirrors are serving our releases, it is the Apache policy to clean old releases from the repo if newer versions are released.
@@ -361,7 +361,7 @@ This can be done like this:
After this, https://dist.apache.org/repos/dist/release/plc4x should only contain the latest release directory.
-=== Releasing the Maven artifacts
+== Releasing the Maven artifacts
The probably simplest part is releasing the Maven artifacts.
@@ -371,7 +371,7 @@ This will move all artifacts into the Apache release repository and delete the s
All release artifacts released to the Apache release repo, will automatically be synced to Maven central.
-=== Merge back release version to `release` branch
+== Merge back release version to `release` branch
The `release branch should always point to the last released version.
This has to be done with git
diff --git a/src/site/asciidoc/developers/release/index.adoc b/src/site/asciidoc/developers/release/index.adoc
index 473cddb5b6b..311fe0ca3a5 100644
--- a/src/site/asciidoc/developers/release/index.adoc
+++ b/src/site/asciidoc/developers/release/index.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/
:icons: font
-== Releasing and Validating Releases
+= Releasing and Validating Releases
diff --git a/src/site/asciidoc/developers/release/release.adoc b/src/site/asciidoc/developers/release/release.adoc
index 4e7ae206740..25de5fa27f2 100644
--- a/src/site/asciidoc/developers/release/release.adoc
+++ b/src/site/asciidoc/developers/release/release.adoc
@@ -17,9 +17,9 @@
:imagesdir: ../../images/
:icons: font
-== Releasing PLC4X
+= Releasing PLC4X
-=== TL/DR
+== TL/DR
IMPORTANT: Please be sure to execute the release with a Java version 11 or the Karaf feature tests will not run.
@@ -57,7 +57,7 @@ IMPORTANT: Please be sure to execute the release with a Java version 11 or the K
* [ ] Merge back release version to `release` branch
* [ ] Send announce email
-=== Preparing your system for being able to release
+== Preparing your system for being able to release
NOTE: Be sure you are using a JDK and not a JRE, or the release will fail because the release can't execute the `javadoc` executable.
@@ -130,7 +130,7 @@ NOTE: On some systems (mainly Mac) gpg signing can result in errors like:
gpg: signing failed: Inappropriate ioctl for device```
In this case adding the following helps: `export GPG_TTY=$(tty)`
-=== Preparing the codebase for a release
+== Preparing the codebase for a release
Usually you will have to update the RELEASE_NOTES document to the new version.
I would suggest doing this prior to the branch as otherwise you will definitely have to port it back to `develop`.
@@ -139,7 +139,7 @@ So remove the `SNAPSHOT` and `(Unreleased)` markers from the file and add missin
Also, if you are doing the first release in a new year, it is advisable to search for the old year and check if any occurrences are ok the way they are.
Usually the `NOTICE` file has to be adjusted.
-=== Creating a release branch
+== Creating a release branch
According to SemVer, we have: Major, Minor and Bugfix releases.
@@ -180,7 +180,7 @@ This step now should perform quite quickly as no build and no tests are involved
However, in the end the versions of the `develop` branch are updated and a new `rel/{current-short-version}` branch is created.
-=== Preparing `develop` for the next iteration
+== Preparing `develop` for the next iteration
Now is a good time to add a new section to the `RELEASE_NOTES` document for the new `SNAPSHOT` version.
@@ -209,7 +209,7 @@ Also be sure to do a quick full-text-search to check if the version was updated
WARNING: If you find anything here, you will need to pay attention during the release.
-=== Release stabilization phase
+== Release stabilization phase
Now usually comes a phase in which last tests and checks should be performed.
@@ -217,7 +217,7 @@ If any problems are found, they have to be fixed in the release branch.
Changes should either be re applied in `develop` or `cherry-picked`, however merging things back can cause a lot of problems, and we no longer have the same versions.
-=== Preparing a release
+== Preparing a release
Same as with creating the branch it is important to enable all profiles when creating the branch as only this way will all modules versions be updated.
Otherwise, the non-default modules on develop will reference the old version which will cause problems when building.
@@ -287,7 +287,7 @@ Also, should you check if you have any uncommitted changes (as our code-generati
However, it will not delete the tag in GIT (locally and remotely). So you have to do that manually or use a different tag next time.
-=== Performing a release
+== Performing a release
This is done by executing another goal of the `maven-release-plugin`:
@@ -328,7 +328,7 @@ This contains all sources of the project and will be what's actually the release
This file will also be signed and `SHA512` hashes will be created.
-=== Staging a release
+== Staging a release
Each new release and release-candidate has to be staged in the Apache SVN under:
@@ -368,7 +368,7 @@ All three `*-source-relese.zip*` artifacts should be located in the directory: `
After committing these files to SVN you are ready to start the vote.
-=== Starting a vote on the mailing list
+== Starting a vote on the mailing list
After staging the release candidate in the Apache SVN, it is time to actually call out the vote.
@@ -442,7 +442,7 @@ Message:
So, the vote passes with {number of +1 votes} +1 votes by PMC members {number of +1 votes from non-pmc members} +1 vote by a non PMC member.
----
-=== Releasing after a successful vote
+== Releasing after a successful vote
As soon as the votes are finished, and the results were in favor of a release, the staged artifacts can be released.
This is done by moving them inside the Apache SVN.
@@ -458,7 +458,7 @@ This will make the release artifacts available and will trigger them being copie
This is also the reason why you should wait at least 24 hours before sending out the release notification emails.
-=== Going back for a new release candidate
+== Going back for a new release candidate
If however for some reason it is needed to prepare a new RC for the release. Please follow these steps:
@@ -486,7 +486,7 @@ If however for some reason it is needed to prepare a new RC for the release. Ple
After this you should be ready to start a new RC.
-=== Cleaning up older release versions
+== Cleaning up older release versions
As a lot of mirrors are serving our releases, it is the Apache policy to clean old releases from the repo if newer versions are released.
@@ -496,7 +496,7 @@ This can be done like this:
After this https://dist.apache.org/repos/dist/release/plc4x should only contain the latest release directory.
-=== Releasing the Maven artifacts
+== Releasing the Maven artifacts
Probably the simplest part is releasing the Maven artifacts.
@@ -506,7 +506,7 @@ This will move all artifacts into the Apache release repository and delete the s
All release artifacts released to the Apache release repo, will automatically be synced to Maven central.
-=== Add the version to the DOAP file
+== Add the version to the DOAP file
Now that the release is out, in the `develop` branch, update the `DOAP` file for plc4x.
@@ -518,7 +518,7 @@ Please add the just released version to the top of the versions.
This file is needed for Apache's tooling to automatically keep track of project release activity, and we use this internally too to automatically update the documentation to always reference the latest released version automatically.
-=== Merge back release version to `release` branch
+== Merge back release version to `release` branch
The `release` branch should always point to the last released version.
This has to be done with git
@@ -539,12 +539,12 @@ git merge -X theirs v{current-full-version}
Possibly a manual conflict resolution has to be done afterwards. After that, changes need to
be pushed.
-=== Updating Jira
+== Updating Jira
1. Set the released version to "released" and set the "release-date"
2. Add the next version to the versions.
-=== Update the download site
+== Update the download site
The URL http://plc4x.apache.org/users/download.html has to be changed, and the current release has to be listed there.
This is done by changing the `download.adoc` under `src/site/users/` (**in the develop branch, as this is where the site is generated from!**)
@@ -557,7 +557,7 @@ _Note: Please add an anchor for the toc_
_Note: Transfer all to ascii-doc notation to ensure correct rendering of the site_
_Also remove the JIRA TICKET ids in Front_
-=== Notifying the world
+== Notifying the world
Make sure you have given the Apache mirrors time to fetch the release files by waiting at least 24 hours after moving the release candidate to the release part of the SVN.
diff --git a/src/site/asciidoc/developers/release/validation.adoc b/src/site/asciidoc/developers/release/validation.adoc
index e5f572b49af..d16222e368d 100644
--- a/src/site/asciidoc/developers/release/validation.adoc
+++ b/src/site/asciidoc/developers/release/validation.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../images/
:icons: font
-== Validating a staged release
+= Validating a staged release
TIP: On MacOS and Linux the first 4 steps can be automated. For details please read the section about tooling after this chapter.
@@ -69,7 +69,7 @@ find . -type f -name 'pom.xml' -exec grep -l "SNAPSHOT" {} \;
* [ ] Build the project according to the information in the README.md file.
* [ ] [RM] Build the project with all `with-xyz` profiles and tests enabled and an empty maven local repo: by appending `-Dmaven.repo.local=../.m2` (On windows use `-D"maven.repo.local"="../.m2"`).
-=== Using RAT
+== Using RAT
Even if we are using RAT to ensure sources have headers in place, still the project can contain exclusions that hide things from the check.
@@ -86,7 +86,7 @@ java -jar apache-rat-0.13.jar apache-plc4x-{current-full-version}-source-release
By piping the result into a text file gives you the chance to investigate the content more easily.
-=== Release Tooling
+== Release Tooling
In the `tools` directory we have a little script that can help with downloading and checking the hashes and signatures automatically.
@@ -103,7 +103,7 @@ After that it will calculate the SHA512 hash and compare it with the staged hash
Last not least it will validate the PGP key and print out some information on it.
-=== Template for the email for voting
+== Template for the email for voting
----
+1/-1 (binding)
diff --git a/src/site/asciidoc/developers/team.adoc b/src/site/asciidoc/developers/team.adoc
index 787754f55bd..42a9482e593 100644
--- a/src/site/asciidoc/developers/team.adoc
+++ b/src/site/asciidoc/developers/team.adoc
@@ -17,12 +17,12 @@
:imagesdir: ../images/
:icons: font
-== Team
+= Team
Sorted by first name:
[width="100%",cols="2,4,1,1",options="header"]
-|=========================================================
+|===
|Name |Bio | |
| *Ben Hutcheson*
@@ -88,3 +88,4 @@ Engineer
pragmatic industries GmbH
Nürtingen |Electrical engineer (HW, SW and interface-stuff) from passion and very new to Apache projects. The more he is involved in open-source the more he likes it, focusing on PLC4X at first. | a|image::team/tmitsch.png[tmitsch, 240, 263]
+|===
\ No newline at end of file
diff --git a/src/site/asciidoc/developers/tools.adoc b/src/site/asciidoc/developers/tools.adoc
index 825229d5f72..c4a68cea013 100644
--- a/src/site/asciidoc/developers/tools.adoc
+++ b/src/site/asciidoc/developers/tools.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../images/
:icons: font
-== Tools
+= Tools
In order to be able to work on PLC4X some tools have kindly been made available to Apache PLC4X committers.
diff --git a/src/site/asciidoc/developers/tutorials/index.adoc b/src/site/asciidoc/developers/tutorials/index.adoc
index 21ded0ee2cc..2016e68c531 100644
--- a/src/site/asciidoc/developers/tutorials/index.adoc
+++ b/src/site/asciidoc/developers/tutorials/index.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/
:icons: font
-== Tutorials
+= Tutorials
diff --git a/src/site/asciidoc/developers/tutorials/testing-serializers-and-parsers.adoc b/src/site/asciidoc/developers/tutorials/testing-serializers-and-parsers.adoc
index 5b55e170498..4a6e1268b2c 100644
--- a/src/site/asciidoc/developers/tutorials/testing-serializers-and-parsers.adoc
+++ b/src/site/asciidoc/developers/tutorials/testing-serializers-and-parsers.adoc
@@ -18,7 +18,7 @@
= Testing Serializers and Parsers
-Currently the build generates the serializers and parsers from a provided `mspec` specification.
+Currently, the build generates the serializers and parsers from a provided `mspec` specification.
A typical full round-trip test for the model, parsers and serializers would look as follows:
diff --git a/src/site/asciidoc/developers/tutorials/writing-driver.adoc b/src/site/asciidoc/developers/tutorials/writing-driver.adoc
index dcf572775b1..583187d992d 100644
--- a/src/site/asciidoc/developers/tutorials/writing-driver.adoc
+++ b/src/site/asciidoc/developers/tutorials/writing-driver.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../../images/
-== Basic Building Blocs of a Driver / Protocol
+= Basic Building Blocs of a Driver / Protocol
The general pipeline for a Protocol looks like the following:
diff --git a/src/site/asciidoc/protocols/ab-eth/index.adoc b/src/site/asciidoc/protocols/ab-eth/index.adoc
index 759a709457b..67ba35fcee2 100644
--- a/src/site/asciidoc/protocols/ab-eth/index.adoc
+++ b/src/site/asciidoc/protocols/ab-eth/index.adoc
@@ -15,12 +15,12 @@
// limitations under the License.
//
-== Allen-Bradley Ethernet
+= Allen-Bradley Ethernet
The Allen-Bradley Ethernet protocol encapsulates a DF1 protocol body to transfer data. The PLC4X driver currently only
supports the protected typed logical read with a limited number of data types.
-=== Connection
+== Connection
The connection string looks as follows: `ab-eth:///`
diff --git a/src/site/asciidoc/protocols/ads/index.adoc b/src/site/asciidoc/protocols/ads/index.adoc
index f586586a6d9..64498ae3580 100644
--- a/src/site/asciidoc/protocols/ads/index.adoc
+++ b/src/site/asciidoc/protocols/ads/index.adoc
@@ -15,11 +15,11 @@
// limitations under the License.
//
-== Beckhoff ADS
+= Beckhoff ADS
Introduction
-=== Links
+== Links
diff --git a/src/site/asciidoc/protocols/canopen/index.adoc b/src/site/asciidoc/protocols/canopen/index.adoc
index 7d9d2b2472e..5e61e1ccd3e 100644
--- a/src/site/asciidoc/protocols/canopen/index.adoc
+++ b/src/site/asciidoc/protocols/canopen/index.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== CANopen
+= CANopen
CANopen is communication protocol built on top of CAN.
CAN is a popular link layer standard which allows exchanging data between nodes and build multi-node applications.
@@ -31,7 +31,7 @@ Please refer the official materials for more details on protocol and its constru
Apache PLC4X is open source project.
It is not a certified product.
-=== Links
+== Links
- https://www.can-cia.org/canopen[CAN in Automation] organization managing specification.
- Public materials published by CAN in Automation: https://www.can-cia.org/en/download/
diff --git a/src/site/asciidoc/protocols/delta-v/index.adoc b/src/site/asciidoc/protocols/delta-v/index.adoc
index 791ece131fa..1ffebaf7a1e 100644
--- a/src/site/asciidoc/protocols/delta-v/index.adoc
+++ b/src/site/asciidoc/protocols/delta-v/index.adoc
@@ -16,14 +16,14 @@
//
:imagesdir: ../../images/
-== DeltaV Industrial Ethernet Communication
+= DeltaV Industrial Ethernet Communication
The DeltaV protocol is used in the Emerson DeltaV system.
In contrast to most other systems, this is a combination of PLC and Control System.
As Emerson seems to insist on the devices not being PLCs, but controllers, well call them this way in this document.
Same with the Control System, these seem to be called OS (Operator System).
-=== Disclaimer
+== Disclaimer
As we had absolutely no information on the details of the protocol, we started by taking an existing DeltaV training system and replaced the network switch with a hub and used this to take network captures of the entire network traffic of the DeltaV network.
@@ -37,7 +37,7 @@ Due to this uncertainty we are only implementing a `promiscuous mode` driver, wh
Read link:reverse-engineering.html[here] for a document on how we proceeded with reverse engineering this protocol.
-=== The Wrapper Protocol
+== The Wrapper Protocol
All communication seems to be done using the `UDP` protocol on port `18507`.
@@ -98,11 +98,11 @@ However we currently have no idea on how this is calculated and we haven't inves
UDP being connectionless the DeltaV network protocol seems to require acknowledging.
This is done by sending a packet back to the originator, but with a length of `0x0000` and the same `type` and mesasge-id` as the packet that is acknowledged.
-=== High Level View of the Protocol
+== High Level View of the Protocol
In this section we'll describe the general structure of how the communication looks like - which message types are sent when and in which sequence.
-==== Connecting an OS to a Controller
+=== Connecting an OS to a Controller
[seqdiag,deltav-connect]
....
@@ -125,7 +125,7 @@ In this section we'll describe the general structure of how the communication lo
}
....
-==== Regular sync
+=== Regular sync
It seems that every 15 seconds two packets are exchanged.
diff --git a/src/site/asciidoc/protocols/delta-v/read-data.adoc b/src/site/asciidoc/protocols/delta-v/read-data.adoc
index 7793bad8f57..a7b9072f797 100644
--- a/src/site/asciidoc/protocols/delta-v/read-data.adoc
+++ b/src/site/asciidoc/protocols/delta-v/read-data.adoc
@@ -16,6 +16,8 @@
//
:imagesdir: ../../images/
+= Data retrieval
+
== 0x0403 (before registration)
Before a subscription is done, regularly (about once a minute) the following packets come in.
diff --git a/src/site/asciidoc/protocols/delta-v/reverse-engineering.adoc b/src/site/asciidoc/protocols/delta-v/reverse-engineering.adoc
index 271c31b8e39..b38c17f380c 100644
--- a/src/site/asciidoc/protocols/delta-v/reverse-engineering.adoc
+++ b/src/site/asciidoc/protocols/delta-v/reverse-engineering.adoc
@@ -16,13 +16,13 @@
//
:imagesdir: ../../images/
-== Reverse Engineering the DeltaV protocol
+= Reverse Engineering the DeltaV protocol
This document should describe what we did in order to reverse-engineer the DeltaV protocol.
The sole purpose of this document, is to write document our path in order to eventually protect ourselves against accusation of using illegal measures in gaining the information we got.
-=== Starting point
+== Starting point
We kindly were provided with access to a DeltaV system used for training.
@@ -42,7 +42,7 @@ With this we let the system run and did a pretty long network capture.
This 29MB WireShark capture was what we started working with.
-=== Identifying the protocol
+== Identifying the protocol
As WireShark didn't have a DeltaV disector, we had to trace it down ourselves.
@@ -50,7 +50,7 @@ When looking at the capture, we very quickly filtered out the usual network prot
Special with all of these was that they all started with a payload of `0xFACE`.
-=== First steps in understanding the protocol
+== First steps in understanding the protocol
Here it appeared that `UDP` packets are sent with some sort of payload, which are obviously responded to by packets with a fixed and very small size (64 bytes).
@@ -68,7 +68,7 @@ When filtering only the `UDP` packets on port `18507` we could scroll though the
In order to prove any assumption we made, we used little programs that used Pcap4J to programmatically check assumptions.
-=== Decoding the wrapper packet header
+== Decoding the wrapper packet header
As mentioned before, it appeared obvious that for almost identical packets the first two short values were very similar too, which led us to the assumption that these are `type` and `sub-type'.
So we wrote a little program, that scanned all the packets and counted how many types we had.
@@ -135,7 +135,7 @@ So we'll just keep that in mind an not worry about interpreting a meaning into t
The last two bytes of the wrapper packet header are simply constantly `0x8000` in every packet.
Here too, we'll just live with knowing that and not wondering what it could mean.
-=== Decoding the internal packet
+== Decoding the internal packet
After having decoded what we think is the wrapper-protocol packet structure, we knew decoding the internal protocol would be a bigger challenge.
@@ -153,7 +153,7 @@ The first two bytes of the payload seem again to relate to a type as similar pac
Especially we did a lot of separate captures for all sorts of different operations.
During this we managed to reverse engineer the connection on the wrapper-protocol layer as well how the communication looks inside the internal protocol.
-==== Connecting
+=== Connecting
When an OS is booted, the following communication could be observed:
@@ -172,7 +172,7 @@ So it seems that In these packets each participant compares it's software state
This does make sense.
When connecting to a remote system, checking the version compatibility is surely an important thing to do.
-==== Normal operation
+=== Normal operation
When just starting the system and not changing anything, we did notice those previously mentioned `0x0006` type messages we think are responsible for keeping the connections in sync.
@@ -183,7 +183,7 @@ It also appears that there is some upper bound for the size of packets.
As when seeing a lot of alarms being sent in 0x0304 messages, sometimes these are split up into multiple messages sent in very short intervals.
The last of these usually being smaller than the rest.
-==== Changing values
+=== Changing values
So now we started changing values.
First we started changing valid values into other valid values.
@@ -197,7 +197,7 @@ Also did we notice the `0x0403` packets seem to contain String constants that re
We assume payload-types starting with `0x04` relate to normal data exchange and ones with `0x03` relating to events and alarms.
-==== Decoding value changes
+=== Decoding value changes
After coming to the conclusion that wrapper-type `0x0002` messages with a payload-type `0x0403` seem to relate to value changes, we started filtering for exactly these packages.
@@ -242,7 +242,7 @@ Right now we are assuming that in one of the other `0x04` packets a subscription
We will hopefully be able to decode this addressing problem in one of our next reverse-engineering sessions.
-==== Decoding Strings
+=== Decoding Strings
As we mentioned before, that we could see content in the packages that were sometimes readable from just looking at the payload, we decided to have another look at these.
diff --git a/src/site/asciidoc/protocols/ehtercat/index.adoc b/src/site/asciidoc/protocols/ehtercat/index.adoc
index 8fecaa9b8a3..4f533f54f99 100644
--- a/src/site/asciidoc/protocols/ehtercat/index.adoc
+++ b/src/site/asciidoc/protocols/ehtercat/index.adoc
@@ -15,11 +15,11 @@
// limitations under the License.
//
-== EtherCAT
+= EtherCAT
Introduction
-=== Links
+== Links
https://www.ethercat.org/default.htm
https://www.ethercat.org/download/documents/EtherCAT_EAP_EN.pdf
diff --git a/src/site/asciidoc/protocols/ethernet-ip/index.adoc b/src/site/asciidoc/protocols/ethernet-ip/index.adoc
index f0c705bd979..ca16129867c 100644
--- a/src/site/asciidoc/protocols/ethernet-ip/index.adoc
+++ b/src/site/asciidoc/protocols/ethernet-ip/index.adoc
@@ -15,11 +15,11 @@
// limitations under the License.
//
-== EtherNet/IP
+= EtherNet/IP
Introduction
-=== Links
+== Links
As of November 2008, The EtherNet/IP Specification consists of three parts: The Common Industrial
Protocol (Volume 1 of the CIP Networks Library), the EtherNet/IP Adaptation of CIP (Volume 2), and the
diff --git a/src/site/asciidoc/protocols/features.adoc b/src/site/asciidoc/protocols/features.adoc
index 2c20eafe903..8f41b8afb26 100644
--- a/src/site/asciidoc/protocols/features.adoc
+++ b/src/site/asciidoc/protocols/features.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Features
+= Features
:icons: font
The following table contains a list of operations and the protocols that support them:
diff --git a/src/site/asciidoc/protocols/index.adoc b/src/site/asciidoc/protocols/index.adoc
index da8c5308bc6..b6314097de9 100644
--- a/src/site/asciidoc/protocols/index.adoc
+++ b/src/site/asciidoc/protocols/index.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Protocols
+= Protocols
- link:ab-eth/index.html[AB-Ethernet]
- link:ads/index.html[DeltaV]
@@ -26,14 +26,14 @@
- link:opc-ua/index.html[OPC-UA]
- link:s7/index.html[S7]
-=== Links
+== Links
Apache 2.0 licensed JNI library for accessing raw IPv4 and IPv6 sockets. Might be the ideal starting point for implementing protocols below TCP & UDP.
https://www.savarese.org/software/rocksaw/
Links to different WireShark captures: https://github.com/automayt/ICS-pcap
-==== BACNet
+=== BACNet
Used in the building automation sector.
http://www.bacnet.org/Addenda/Add-135-2008t.pdf
@@ -41,7 +41,7 @@ http://www.bacnet.org/Addenda/Add-135-2008t.pdf
AKA: ISO 16484-5:
The official specification can be purchased here: https://www.iso.org/standard/71935.html
-==== IEC 61850
+=== IEC 61850
Used by the IDS SAS (station automation system)
diff --git a/src/site/asciidoc/protocols/modbus/index.adoc b/src/site/asciidoc/protocols/modbus/index.adoc
index 7a1092eba37..58e2c65e2d2 100644
--- a/src/site/asciidoc/protocols/modbus/index.adoc
+++ b/src/site/asciidoc/protocols/modbus/index.adoc
@@ -15,11 +15,11 @@
// limitations under the License.
//
-== Modbus
+= Modbus
Introduction
-=== Links
+== Links
- Main Landing Page: http://www.modbus.org/tech.php
- Modbus Protocol Spec: http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf
diff --git a/src/site/asciidoc/protocols/opc-ua/index.adoc b/src/site/asciidoc/protocols/opc-ua/index.adoc
index 82973c0edc1..01766965876 100644
--- a/src/site/asciidoc/protocols/opc-ua/index.adoc
+++ b/src/site/asciidoc/protocols/opc-ua/index.adoc
@@ -15,11 +15,11 @@
// limitations under the License.
//
-== OPC-UA
+= OPC-UA
Introduction
-=== Links
+== Links
https://opcfoundation.org/developer-tools/specifications-unified-architecture/part-1-overview-and-concepts
diff --git a/src/site/asciidoc/protocols/s7/index.adoc b/src/site/asciidoc/protocols/s7/index.adoc
index bb17ec7a4fa..0b734e4b648 100644
--- a/src/site/asciidoc/protocols/s7/index.adoc
+++ b/src/site/asciidoc/protocols/s7/index.adoc
@@ -16,14 +16,14 @@
//
:imagesdir: ../../images/
-== S7 Communication
+= S7 Communication
When communicating with S7 Devices there is a whole family of protocols, that can be used.
In general you can divide them into `Profinet` protocols and `S7 Comm` protocols.
The later are far simpler in structure, but also far less documented.
The `S7 Comm` protocols are generally split up into two flavours: The classic `S7 Comm` and a newer version unofficially called `S7 Comm Plus`.
-=== Overview of the Protocols
+== Overview of the Protocols
[ditaa,protocols-s7-osi]
....
@@ -83,7 +83,7 @@ The `S7 Comm` protocols are generally split up into two flavours: The classic `S
- - - - - - - - - - +-------------------------------------------------------------------------------------------------+ - -
....
-=== Protocol Descriptions
+== Protocol Descriptions
|===
|Name |ISO |RFC |Link
@@ -96,7 +96,7 @@ The `S7 Comm` protocols are generally split up into two flavours: The classic `S
|DCOM |- |- | https://msdn.microsoft.com/library/cc201989.aspx
|===
-=== Interaction with an S7 PLC
+== Interaction with an S7 PLC
Currently we are concentrating on implementing the TCP-based variants of the `S7 Comm` and `S7 Comm Plus` protocols.
Both are transferred using `ISO TP` which is wrapped by `ISO on TCP`.
@@ -140,7 +140,7 @@ Each message is called a `TPDU` (Transport Protocol Data Unit):
Notice: There is no `Disconnect Response` in `ISO TP: Class 0`.
-==== Connection Request TPDU
+=== Connection Request TPDU
// len (length of bits - use instead of explicit byte count - requires "*" as first element)
// label
@@ -198,11 +198,11 @@ Legend:
- [protocolId]#Part of the packet that identifies the type of request#
- [protocolParameter]#Variable Parts of the ISO Transport Protocol Packet Header#
-==== Connection Response TPDU
+=== Connection Response TPDU
The `Connection Response` is identical to the `Connection Request` with the only difference that the `TPDU-Code` has a code of `0xD0`.
-==== Data TPDU
+=== Data TPDU
// len (length of bits - use instead of explicit byte count - requires "*" as first element)
// label
diff --git a/src/site/asciidoc/protocols/s7/s7comm-plus.adoc b/src/site/asciidoc/protocols/s7/s7comm-plus.adoc
index 529500a5f15..2c1f8fa7757 100644
--- a/src/site/asciidoc/protocols/s7/s7comm-plus.adoc
+++ b/src/site/asciidoc/protocols/s7/s7comm-plus.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../../images/
-== S7 Comm Plus (0x72)
+= S7 Comm Plus (0x72)
The `S7 Comm Plus` protocol is a new version of the original `S7 Comm` protocol.
While a `S7 Comm` packet is identified, by the magic byte `0x32`, the `S7 Comm Plus` packet uses the magic byte `0x72`.
diff --git a/src/site/asciidoc/protocols/s7/s7comm.adoc b/src/site/asciidoc/protocols/s7/s7comm.adoc
index 3b97a43ef39..3d25f6d9aaf 100644
--- a/src/site/asciidoc/protocols/s7/s7comm.adoc
+++ b/src/site/asciidoc/protocols/s7/s7comm.adoc
@@ -16,9 +16,9 @@
//
:imagesdir: ../../images/
-== S7 Comm (0x32)
+= S7 Comm (0x32)
-=== General
+== General
While a lot of information was available on the general structure of S7 communication, only little information was available on the constant values this protocol uses.
If information was available, this was mostly provided with a GPL license and therefore was disqualified for being used in this project.
@@ -30,7 +30,7 @@ As soon as a valid value was found the tool then output the detected constant va
The tool for generating this is located in the `plc4j/protocols/s7-utils` project.
-=== Structure of a Setup Communication Request
+== Structure of a Setup Communication Request
[packetdiag,s7-setup-communication-request,svg]
....
@@ -78,7 +78,7 @@ Legend:
- [protocolId]#Part of the packet that identifies the type of request#
- [protocolParameter]#Variable Parts of the ISO Transport Protocol Packet Header#
-=== Structure of a Setup Communication Response
+== Structure of a Setup Communication Response
The `Setup Communication Response` is identical to the `Setup Communication Request` with the only difference that the `Message Type` has an ACK_DATA code of `0x03`.
@@ -88,7 +88,7 @@ The values might be lower than in the request, but never higher.
TIP: One thing about `Setup Communication Responses` which is kind of strange, is that usually S7 response messages have additional `error class` and `error code` fields, which this type of response doesn't seem to have.
-=== Sizes of requests
+== Sizes of requests
During the connection to a S7 PLC the client and PLC agree on 3 important parameters:
@@ -134,7 +134,7 @@ Same should sometimes be possible in the other direction.
So if we wanted to read 300 bytes with a 256 byte TPDU size, the driver would split this up into two smaller byte arrays and internally merge them. However when reading Real (Number) values there could be issues with this.
However in this case the driver has to completely take care of this optimization.
-=== Links
+== Links
Providing some additional information without directly being used:
diff --git a/src/site/asciidoc/users/adopters.adoc b/src/site/asciidoc/users/adopters.adoc
index da17829a85f..4b2d61652de 100644
--- a/src/site/asciidoc/users/adopters.adoc
+++ b/src/site/asciidoc/users/adopters.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../images/
:icons: font
-== Companies using Apache PLC4X
+= Companies using Apache PLC4X
image::toddy-loves-apache.png[width=200,float=left]
diff --git a/src/site/asciidoc/users/blogs-videos-and-slides.adoc b/src/site/asciidoc/users/blogs-videos-and-slides.adoc
index bd591e4bfb4..dc0f1e524bd 100644
--- a/src/site/asciidoc/users/blogs-videos-and-slides.adoc
+++ b/src/site/asciidoc/users/blogs-videos-and-slides.adoc
@@ -15,15 +15,15 @@
// limitations under the License.
//
-== Blogs, Videos and Slides on Apache PLC4X
+= Blogs, Videos and Slides on Apache PLC4X
-=== Blog posts
+== Blog posts
- https://medium.com/@megachucky/apache-kafka-ksql-and-apache-plc4x-for-iiot-data-integration-and-processing-472c2de6700b[Apache Kafka, KSQL and Apache PLC4X for IIoT Data Integration and Processing]
- https://blog.codecentric.de/2018/06/edge-computing-industrial-iot-apache-edgent-apache-plc4x/[Edge Computing und Industrial IoT mit Apache Edgent und Apache PLC4X]
- https://riot.community/examples/http-plc4x.html[Advanced: Exposing a PLC as JSON Web Services (using PLC4X)]
-=== Videos & Webinars
+== Videos & Webinars
- https://youtu.be/1vf3zw7HQws[High Security Iiot Communication With Apache Plc4X, Apache Asia Con, August 2021]
- https://youtu.be/ogsFTnQhtIU[Apache Plc4X For Can Bus And Canopen, Apache Asia Con, August 2021]
@@ -39,7 +39,7 @@
- https://aceu19.apachecon.com/session/idea-apache-tlp[From an idea to an Apache TLP]
- https://mediathek.hhu.de/watch/6014a3fd-aadf-4bcf-adf6-3134162aef1b[Wie wir mit Apache PLC4X die Silos in der Automatisierungsindustrie aufbechen]
-=== Slides
+== Slides
- https://de.slideshare.net/KaiWaehner/iiot-industry-40-with-apache-kafka-connect-ksql-apache-plc4x[Apache Kafka, KSQL and Apache PLC4X for IIoT Data Integration and Processing]
- https://de.slideshare.net/ChristoferDutz/episode-iv-a-new-hope-229731756[Episode iv a new hope - Industry 4.0 done our way]
diff --git a/src/site/asciidoc/users/commercial-support.adoc b/src/site/asciidoc/users/commercial-support.adoc
index ed80b9e0af6..f6adaf3e5c8 100644
--- a/src/site/asciidoc/users/commercial-support.adoc
+++ b/src/site/asciidoc/users/commercial-support.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../images/
:icons: font
-== Commercial support offerings for Apache PLC4X
+= Commercial support offerings for Apache PLC4X
image::toddy-loves-apache.png[width=200,float=left]
@@ -40,11 +40,11 @@ a|image::users/companies/logo-timecho.png[timecho, 200, 200] |https://www.timec
|===
-=== Who can be added to this list?
+== Who can be added to this list?
Anyone who provides `Apache PLC4X` related services can be added to this list (e.g. training, consulting, custom software development, support, installation or related services).
-=== How can I get added to this list?
+== How can I get added to this list?
Please create a Pull-Request on GitHub as described https://plc4x.apache.org/developers/contributing.html[here]. The resource requiring editing can be found https://github.com/apache/plc4x/blob/develop/src/site/asciidoc/users/commercial-support.adoc[here]
diff --git a/src/site/asciidoc/users/download.adoc b/src/site/asciidoc/users/download.adoc
index cf1edee462e..c0436e5b65f 100644
--- a/src/site/asciidoc/users/download.adoc
+++ b/src/site/asciidoc/users/download.adoc
@@ -15,11 +15,11 @@
// limitations under the License.
//
-== Download
+= Download
Be sure to verify your downloads by these https://www.apache.org/info/verification[procedures] using these https://downloads.apache.org/plc4x/KEYS[KEYS] for any Apache release.
-=== Current Releases
+== Current Releases
==== 0.12.0 Official https://www.apache.org/dyn/closer.lua/plc4x/0.12.0/apache-plc4x-0.12.0-source-release.zip[source release] [ https://downloads.apache.org/plc4x/0.12.0/apache-plc4x-0.12.0-source-release.zip.sha512[SHA512] ] [ https://downloads.apache.org/plc4x/0.12.0/apache-plc4x-0.12.0-source-release.zip.asc[ASC] ]
@@ -32,7 +32,7 @@ This release was mainly a release containing many bugfixes. We literally halved
- Which of these configuration options are required?
- The same set of information is also available for the transports a driver is using.
-===== New Features
+==== New Features
- API: Made several bits of information available via the API
allowing tools to provide more content assist when dealing
@@ -45,7 +45,7 @@ and Simulated drivers.
- The OPC-UA Java driver now support certificate-based
authentication and encryption.
-===== Incompatible changes
+==== Incompatible changes
- Java 8 is no longer officially supported and Java 11 is the
new base-line.
@@ -60,7 +60,7 @@ new base-line.
config options in the connection-string was updated to be
now prefixed with the transport name the option belongs to.
-===== Bug Fixes
+==== Bug Fixes
- S7: Several bugs and issues regarding supporting various
duration, date and time data-types.
@@ -71,7 +71,7 @@ numbers.
improved.
- Core: Fixed several leaks of open threads.
-=== Previous Releases
+== Previous Releases
==== 0.11.0 Official https://archive.apache.org/dist/plc4x/0.11.0/apache-plc4x-0.11.0-source-release.zip[source release] [ https://downloads.apache.org/plc4x/0.11.0/apache-plc4x-0.11.0-source-release.zip.sha512[SHA512] ] [ https://downloads.apache.org/plc4x/0.11.0/apache-plc4x-0.10.0-source-release.zip.asc[ASC] ]
@@ -79,7 +79,7 @@ The APIs have been streamlined in a preparation for a hopefully soon 1.0.0 relea
Many drivers have been re-implemented with much more features.
Integration modules have been improved.
-===== New Features
+==== New Features
- Implemented a `PLC4X-Server` and `PLC4X-Driver` that allows
using the server as a proxy for communicating with PLCs.
@@ -92,7 +92,7 @@ communication, which however can be tunneled through a
- The KNX driver in Java now supports reading "knxproj" files
exported from the new ETS version 6.
-===== Bug Fixes
+==== Bug Fixes
- The name of the Modbus TCP driver was changed from "modbus"
to "modbus-tcp".
@@ -121,7 +121,7 @@ This is a bugfix release aiming at directly fixing CVE-2021-43083 as well as upd
Please note that CVE-2021-43083 only affects the PLC4C part of PLC4X.
-===== Bug Fixes
+==== Bug Fixes
CVE-2021-43083 Apache PLC4X 0.9.0 Buffer overflow in PLC4C via crafted server response
@@ -132,7 +132,7 @@ This is an ordinary PLC4X release, containing changes that
accumulated over time. It doesn't have an explicit focus on
a particular topic.
-===== New Features
+==== New Features
- The OPC UA driver has been replaced with a native driver. Previously
Eclipse Milo was being used.
@@ -143,9 +143,9 @@ Eclipse Milo was being used.
- Major cleanup of PLC4C
- S7 Driver now supports event and alarm handling on some S7 models
-===== Incompatible changes
+==== Incompatible changes
-===== Bug Fixes
+==== Bug Fixes
PLC4X-200 OPC-UA Driver not connecting if params string is not provided
PLC4X-201 OPC-UA PlcList underlying type not compatible with Eclipse Milo
@@ -168,7 +168,7 @@ This is an ordinary PLC4X release, containing changes that
accumulated over time. It doesn't have an explicit focus on
a particular topic.
-===== New Features
+==== New Features
- The KNXnet/IP Driver now supports writing of values.
- The Modbus driver now supports more common notations of Modbus addresses using a pure-numeric notation.
@@ -177,7 +177,7 @@ a particular topic.
- Integration with the Milo OPC UA Server is now available.
- Kafka Connect workers have been updated source and sink connectors are now included.
-===== Incompatible changes
+==== Incompatible changes
- The syntax of the S7 addresses changed slightly allowing to provide a string length. Without this, a STRING datatype will read 254 characters, by adding the size in round brackets to the type name will use the specified number.
@@ -191,7 +191,7 @@ a particular topic.
- The PLCValue types have been refactored to align with the types defined in IEC 61131-3 (https://en.wikipedia.org/wiki/IEC_61131-3) directly using the older Java types (PlcBoolean) is no longer possible.
-===== Bug Fixes
+==== Bug Fixes
A lot of testing was done regarding the IEC 61131-3 data-types.
This resulted in numerous bugfixes in many protocols.
@@ -226,7 +226,7 @@ core. All previous driver versions are now considered deprecated
and have been replaced by versions using the new driver structure
and generated driver codebase.
-===== New Features
+==== New Features
- Drivers now support structured types using PlcValues
- The EIP (EtherNet/IP) driver no longer requires an external
@@ -242,7 +242,7 @@ significant performance gains when writing multiple vlaues)
to be able to use them in an OSGi container.
- New Firmata protocol driver
-===== Incompatible changes
+==== Incompatible changes
- Due to the refactoring of the driver core there might be issues
running drivers built against older core versions.
@@ -255,7 +255,7 @@ https://plc4x.apache.org/users/protocols/s7.html
- The karaf-feature modules are removed as the drivers now all
provide both a feature.xml as well as a `kar` bundled archive
-===== Bug Fixes
+==== Bug Fixes
- PLC4X-174 UDP Transport does not accept ports containing 0
- PLC4X-134 S7 is terminating the connection during handshake
@@ -271,16 +271,16 @@ most users have switched to 0.7 and above (with generated drivers).
If you are using the S7 Driver you should update to this Version
as the critical (memory leak) bug PLC4X-163 is fixed.
-===== New Features
+==== New Features
- PLC4X-168 A shorter S7 Field Syntax is Introduced.
This release contains no further features and mostly stabilization.
-===== Incompatible changes
+==== Incompatible changes
- Moved the C++, C# and Python drivers into the `sandbox`
-===== Bug Fixes
+==== Bug Fixes
- Fixed Promise Chain for InternalPlcWriteRequest
- PLC4X-45 Add float support to Modbus Protocol
@@ -294,7 +294,7 @@ This release contains no further features and mostly stabilization.
This is the first release containing our new generated drivers (AB-ETH)
-===== New Features
+==== New Features
- Implemented a new Apache Kafka Connect integration module
- Implemented a new Apache NiFi integration module
@@ -307,9 +307,9 @@ Sandbox (Beta-Features)
- Implemented a new BACnet/IP passive mode driver
- Implemented a new Serial DF1 driver
-===== Incompatible changes
+==== Incompatible changes
-===== Bug Fixes
+==== Bug Fixes
- PLC4X-104 S7 Driver Datatype TIME_OF_DAY causes ArrayOutOfBoundException
- PLC4X-134 S7 is terminating the connection during handshake
@@ -322,7 +322,7 @@ Sandbox (Beta-Features)
This is the first release of Apache PLC4X as top-level project.
-===== New Features
+==== New Features
- The PlcConnection now supports a `ping` method to allow checking if an existing connection is still alive.
- Support of the OPC-UA protocol with the `opc-ua-driver`.
@@ -331,25 +331,25 @@ This is the first release of Apache PLC4X as top-level project.
-- Added first versions of a Python PLC4X API (`plc4py`)
- Added an Interop server which allows to relay requests from other languages to a Java Server
-===== Incompatible changes
+==== Incompatible changes
- ElasticSearch example was updated to use ElasticSearch 7.0.1, this might cause problems with older Kibana versions.
-===== Bug Fixes
+==== Bug Fixes
-=== Incubating Releases
+== Incubating Releases
==== 0.3.1 (incubating) Official https://archive.apache.org/dist/incubator/plc4x/0.3.1-incubating/apache-plc4x-incubating-0.3.1-source-release.zip[source release] [ https://archive.apache.org/dist/incubator/plc4x/0.3.1-incubating/apache-plc4x-incubating-0.3.1-source-release.zip.sha512[SHA512] ] [ https://archive.apache.org/dist/incubator/plc4x/0.3.1-incubating/apache-plc4x-incubating-0.3.1-source-release.zip.asc[ASC] ]
-===== New Features
+==== New Features
- No new features
-===== Incompatible changes
+==== Incompatible changes
- No incompatible changes.
-===== Bug Fixes
+==== Bug Fixes
- The S7 driver didn't correctly handle "fill-bytes" in multi-item read-responses and multi-item write-requests
- Fixed NPE when reading odd-length array of one-byte base types
@@ -359,7 +359,7 @@ This is the first release of Apache PLC4X as top-level project.
[#release-0_3_0]
==== 0.3.0 (incubating) Official https://archive.apache.org/dist/incubator/plc4x/0.3.0-incubating/apache-plc4x-incubating-0.3.0-source-release.zip[source release] [ https://archive.apache.org/dist/incubator/plc4x/0.3.0-incubating/apache-plc4x-incubating-0.3.0-source-release.zip.sha512[SHA512] ] [ https://archive.apache.org/dist/incubator/plc4x/0.3.0-incubating/apache-plc4x-incubating-0.3.0-source-release.zip.asc[ASC] ]
-===== New Features
+==== New Features
- Object PLC Mapping (OPM) now has a Alias Registry to allow
variable substitution at runtime and write support
@@ -368,7 +368,7 @@ This is the first release of Apache PLC4X as top-level project.
- New integration `apache-karaf` to enable plc4j in a karaf
runtime environment
-===== Incompatible changes
+==== Incompatible changes
- The 'plc4j-core' module has been merged into 'plc4j-api'.
So there is no 'plc4j-core' module anymore. Just remove that
@@ -377,7 +377,7 @@ This is the first release of Apache PLC4X as top-level project.
a `plc4j-protocol-{name}` you now need to change this to
`plc4j-driver-{name}`
-===== Bug Fixes
+==== Bug Fixes
- Fixing dependency to the wrap url-handler
- When receiving responses with more than 512 byte, the IsoOnTcp protocol doesn't work
@@ -388,7 +388,7 @@ This is the first release of Apache PLC4X as top-level project.
[#release-0_2_0]
==== 0.2.0 (incubating) Official https://archive.apache.org/dist/incubator/plc4x/0.2.0-incubating/apache-plc4x-incubating-0.2.0-source-release.zip[source release] [ https://archive.apache.org/dist/incubator/plc4x/0.2.0-incubating/apache-plc4x-incubating-0.2.0-source-release.zip.sha512[SHA512] ] [ https://archive.apache.org/dist/incubator/plc4x/0.2.0-incubating/apache-plc4x-incubating-0.2.0-source-release.zip.asc[ASC] ]
-===== Changes:
+==== Changes:
* Changed API: instead of passing request object to `read({read-request})`, `write({write-request})` or `subscribe({subscribe-request})` methods now the `execute()` method is called on the request itself
* New Connection Pool component
diff --git a/src/site/asciidoc/users/getting-started/general-concepts.adoc b/src/site/asciidoc/users/getting-started/general-concepts.adoc
index 0df85ea25c9..bb5d70e1757 100644
--- a/src/site/asciidoc/users/getting-started/general-concepts.adoc
+++ b/src/site/asciidoc/users/getting-started/general-concepts.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== General Concepts
+= General Concepts
On this page we'll give a short introduction to the most important concepts that will help you understand Apache PLC4X better.
@@ -33,7 +33,7 @@ Both are pretty dependent on the type of device you are planning to communicate
If you are familiar with `JDBC` or `ODBC`, you will easily understand the concepts in PLC4X, as these were a great inspiration for the creation of Apache PLC4X.
-=== Connections
+== Connections
In general a connection is a physical or logical connection between two endpoints.
@@ -65,7 +65,7 @@ From a driver point of view there is actually no difference between a `Raw Socke
The `Test` transport is generally built for being used inside the PLC4X test framework as it allows fine-grained access to the input and output of the drivers. With the test transport we can explicitly control which data is passed into and retrieved from drivers and to validate this in unit- and integration-tests.
-==== Connection Strings
+=== Connection Strings
A fully qualified PLC4X connection string would look like this:
@@ -103,7 +103,26 @@ The shortest version of a fully qualified connection string would look something
For more information on the default settings for a given protocol or transport, please check the corresponding drivers documentation.
-=== Individual Resource Addresses (Tags)
+== Individual Resource Addresses (Tags)
Addresses for individual tags on a PLC are extremely dependent on the used protocol.
As we usually decided to stick to the address formats that are used in those particular environments, please check the `Protocol Documentation` on details about these address formats link:../protocols/index.html[here].
+
+The tag syntax is fairly generic and can be summarized as `type:address`.
+Some protocols might support tag attributes which are specified as key-value pairs after primary tag address.
+For example `coil:1{unit-id: 10}`.
+Tag attributes are additional elements which depend on actual protocol.
+
+== Tag metadata
+
+Starting from Apache PLC4X release 0.13 an experimental support for result set metadata is provided in plc4j.
+This metadata is dedicated to provide additional information which might be available at protocol (sample timestamp) or driver level (i.e. packet receive time).
+Consult again protocol documentation on specifics of this feature.
+
+The common metadata keys currently defined are:
+
+* timestamp - timestamp for tag value provided by other communication party.
+* timestamp_source - source of timestamp or receive_timestamp field, if any of these is provided.
+* receive_timestamp - timestamp assumed upon receiving of packet with data.
+
+
diff --git a/src/site/asciidoc/users/getting-started/index.adoc b/src/site/asciidoc/users/getting-started/index.adoc
index 41f0a5b72ee..c634db80e17 100644
--- a/src/site/asciidoc/users/getting-started/index.adoc
+++ b/src/site/asciidoc/users/getting-started/index.adoc
@@ -15,14 +15,14 @@
// limitations under the License.
//
-== Getting Started
+= Getting Started
Depending on the programming language, the usage will differ, therefore please go to the `Getting Started` version of the language of choice.
-=== Go/Golang
+== Go/Golang
For guides on how to write PLC4X applications with Go, please go to the link:plc4go.html[Go Getting Started]
-=== Java
+== Java
For guides on how to write PLC4X applications with Java, please go to the link:plc4j.html[Java Getting Started]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/getting-started/opcua-client-certificate.adoc b/src/site/asciidoc/users/getting-started/opcua-client-certificate.adoc
new file mode 100644
index 00000000000..76205d19ed1
--- /dev/null
+++ b/src/site/asciidoc/users/getting-started/opcua-client-certificate.adoc
@@ -0,0 +1,128 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+:imagesdir: ../../images/tutorials/opcua/kse
+:icons: font
+:experimental:
+
+= OPC UA : Client certificate creation
+
+Below tutorial will teach you how to create client certificate for use within production environments.
+This tutorial focuses on preparation of configuration.
+It does not dive in X.509 and PKI details nor specifics of any OPC-UA server.
+
+The Apache PLC4X client, as many other UA clients is able to create ad-hoc certificate for communication.
+While it softens entry bearer for many, it creates also a gap when with secured environments, which control certificate chains.
+
+There are several ways on how to organize certificates.
+In this little tutorial we will use open source tool called https://github.com/kaikramer/keystore-explorer[KeyStore Explorer], referred herein as KSE.
+This tool allows to create files which can be used as a cryptographic keystore for Java-based programs but not only.
+One of nice things which Java runtime introduced, was change of default keystore format from JKS (Java KeyStore) to https://en.wikipedia.org/wiki/PKCS_12[PKCS#12].
+
+== Creating self-signed certificate using KSE
+Install the tool using the way which is valid for your operating system, then open the tool.
+
+Entire process can be observed in below short screen capture:
+
+image::kse_self_signed_ca_certificate.gif["Creation of self-signed certificate authority using KeyStore Explorer"]
+
+Step by step operations are.
+
+. Navigate to menu:File[New] or press kbd:[CTRL+N] to create new keystore.
++
+image::kse_1.png["Create new keystore"]
+
+. Pick PKCS#12 as desired store format.
++
+image::kse_2.png["Use PKCS#12 format"]
+
+. Navigate to menu:Tools[Generate key pair] or press kbd:[CTRL+G]:
++
+image::kse_3.png["Create new key pair"]
+
+. Decide on key type (RSA, DSA, EC) and its size. RSA is a fairly common, confirm key size and click btn:[OK]
++
+image::kse_4.png["Pick key type and size"]
+
+. KSE will ask you about certificate details
++
+image::kse_5.png["Certificate settings"]
+
+. Go to `Name` field and click little phone book icon and click it.
+You will be able to specify common name (CN), organization unit (OU) and other fields, and confirm with btn:[OK]
++
+image::kse_6.png["Certificate name details"]
+
+. Click btn:[Add Extensions], which is located below `Name` field (you will again see step 5 window), it will open next popup.
++
+image::kse_7.png["Add extension popup"]
+
+. Click btn:[Use Standard Template], select CA, then click btn:[OK].
++
+image::kse_8.png["Use CA template"]
+
+. This will fill extensions with few rows, but do not close this window yet.
++
+image::kse_9.png["CA certificate extensions details"]
+
+. Click btn:[+] next to the list, and select `Subject Alternative Name`, then click btn:[OK].
++
+image::kse_10.png["Add subject name"]
+
+. You will see again window with list, click btn:[+] next to it.
++
+image::kse_11.png["Subject alternative names list"]
+
+. Select `URI`, and type client identifier in `General Name Value` field (i.e. `urn:my:plc:client`), and confirm via btn:[OK].
++
+image::kse_12.png["Add subject alternative name"]
+
+. Click btn:[OK] to close certificate extensions prompt.
+. Click btn:[OK] to finish certificate creation.
+. Enter key pair alias and confirm with btn:[OK].
++
+image::kse_13.png["Specify key pair alias"]
+
+. Enter private key password, confirm it in second field and click btn:[OK].
++
+image::kse_14.png["Specify private key password"]
+
+. Upon completion of these steps you should be presented with "Key Pair Generation Successful" message.
++
+image::kse_15.png["Completion of key generation"]
+
+. Navigate to menu:File[Save] or press kbd:[CTRL+S] to save keystore.
++
+image::kse_16.png["Save keystore"]
+
+. Enter keystore password, for use within Java **it must be same as private key password**.
++
+image::kse_17.png["Save keystore"]
+
+. Specify file location.
++
+image::kse_17.png["Save keystore"]
+
+. Close KSE, your client private key and certificate is ready for use.
+
+== Usage within OPC UA PLC4X client
+
+For detailed use of options used to configure client please refer to documentation of Apache PLC4X OPC-UA driver.
+Please remember that keystore must be readable by your program.
+In case if you are not certain what is working directory of your program, specify full path to keystore.
+
+
+
diff --git a/src/site/asciidoc/users/getting-started/plc4c.adoc b/src/site/asciidoc/users/getting-started/plc4c.adoc
index 358f781bb27..99327ed3d4a 100644
--- a/src/site/asciidoc/users/getting-started/plc4c.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4c.adoc
@@ -15,4 +15,4 @@
// limitations under the License.
//
-== Getting Started with C
\ No newline at end of file
+= Getting Started with C
\ No newline at end of file
diff --git a/src/site/asciidoc/users/getting-started/plc4cs.adoc b/src/site/asciidoc/users/getting-started/plc4cs.adoc
index 465c1a44364..f476a8b89a7 100644
--- a/src/site/asciidoc/users/getting-started/plc4cs.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4cs.adoc
@@ -15,4 +15,4 @@
// limitations under the License.
//
-== Getting Started with C#
\ No newline at end of file
+= Getting Started with C#
\ No newline at end of file
diff --git a/src/site/asciidoc/users/getting-started/plc4go.adoc b/src/site/asciidoc/users/getting-started/plc4go.adoc
index 105b2245dfc..672ae5b48d4 100644
--- a/src/site/asciidoc/users/getting-started/plc4go.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4go.adoc
@@ -15,9 +15,9 @@
// limitations under the License.
//
-== Getting Started with Go
+= Getting Started with Go
-=== Initializing a dummy project
+== Initializing a dummy project
Just in case you want to get started with `Go`. In this part we'll setup a new `Go` project.
If you are familiar with this, you can go to the next chapter.
@@ -58,7 +58,7 @@ You will execute your first `Go` progran ... however the output is rather underw
You're now ready to continue.
-=== Using the PLC4Go API directly
+== Using the PLC4Go API directly
In order to write a valid PLC4X Go application, all you need, is to add a dependency to the `plc4go module`.
Now all you need to do, is execute the following command:
@@ -77,7 +77,7 @@ Perhaps we'll change this in the future, but for now all comes in one bundle.
Now you're generally set to start writing your first `PLC4Go` program.
-==== Connecting to a PLC
+=== Connecting to a PLC
In contrast to PLC4J, which uses the service lookup to find the `transports` and the `drivers` automatically, in `PLC4Go` they need to be manually registered at the driver manager.
diff --git a/src/site/asciidoc/users/getting-started/plc4j.adoc b/src/site/asciidoc/users/getting-started/plc4j.adoc
index c98d7feda19..5f4a3eeff7a 100644
--- a/src/site/asciidoc/users/getting-started/plc4j.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4j.adoc
@@ -15,9 +15,9 @@
// limitations under the License.
//
-== Getting Started with Java
+= Getting Started with Java
-=== Using the PLC4J API directly
+== Using the PLC4J API directly
In order to write a valid PLC4X Java application, all you need, is to add a dependency to the `api module`.
When using Maven, all you need to do is add this dependency:
@@ -79,7 +79,7 @@ But there are some cases in which we can't simulate or features are simply disab
Therefore, we use metadata to check programmatically, if a given feature is available.
-==== Reading Data
+=== Reading Data
----
// Check if this connection support reading of data.
@@ -185,7 +185,7 @@ PLC4X provides getters and setters for a wide variety of Java types and automati
However, when for example trying to get a long-value as a byte and the long-value exceeds the range supported by the smaller type, a `RuntimeException` of type `PlcIncompatibleDatatypeException`.
In order to avoid causing this exception to be thrown, however there are `isValid{TypeName}` methods that you can use to check if the value is compatible.
-==== Writing Data
+=== Writing Data
In general the structure of code for writing data is extremely similar to that of reading data.
@@ -241,7 +241,7 @@ for (String tagName : response.getTagNames()) {
}
----
-==== Subscribing to Data
+=== Subscribing to Data
Subscribing to data can be considered similar to reading data, at least the subscription itself if very similar to reading of data.
diff --git a/src/site/asciidoc/users/getting-started/plc4py.adoc b/src/site/asciidoc/users/getting-started/plc4py.adoc
index f2e0411e3f2..1d19bf1db7d 100644
--- a/src/site/asciidoc/users/getting-started/plc4py.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4py.adoc
@@ -15,9 +15,9 @@
// limitations under the License.
//
-== Getting Started with Python
+= Getting Started with Python
-=== Using the PLC4PY API directly
+== Using the PLC4PY API directly
Currently, you need to install PLC4Py from the GitHub repository instead of pypi.
Once we have decided that PLC4Py is in a position to release we will publish to pypi.
@@ -54,10 +54,10 @@ async def communicate_with_plc():
builder.add_item("Random Tag", "4x00001[10]")
request = builder.build()
print(f"Request built")
- print(f"Executing request")
- response = await connection.execute(request)
- print(f"Request executed")
- print(f"Response code: {response.response_code}")
+ print(f"Executing request")
+ response = await connection.execute(request)
+ print(f"Request executed")
+ print(f"Response code: {response.response_code}")
asyncio.run(communicate_with_plc())
----
@@ -69,11 +69,12 @@ The basic functions supported by PLCs and therefore supported by PLC4X are:
* Discover Devices (Not yet available for PLC4Py)
* List resources in the PLC
* Read data
-* Write data (Not yet available for PLC4Py)
+* Write data
* Subscribe for data (Not yet available for PLC4Py)
In general, we will try to offer as many features as possible.
-So if a protocol doesn't support subscription based communication it is our goal to simulate this by polling in the background, so it is transparent for the users (This simulation feature hasn't been implemented yet though, but it's on our roadmap).
+So if a protocol doesn't support subscription based communication it is our goal to simulate this by polling in the background,
+so it is transparent for the users (This simulation feature hasn't been implemented yet though, but it's on our roadmap).
But there are some cases in which we can't simulate or features are simply disabled intentionally:
@@ -81,12 +82,12 @@ But there are some cases in which we can't simulate or features are simply disab
Therefore, we use metadata to check programmatically, if a given feature is available.
-==== Reading Data
+=== Reading Data
----
# Check if this connection support reading of data.
-if connection.is_read_supported():
+if not connection.is_read_supported():
logger.error("This connection doesn't support reading.")
----
@@ -105,7 +106,8 @@ with connection.read_request_builder() as builder:
So, as you can see, you prepare a request, by adding tag addresses to the request and in the end by calling the `build` method.
-If you are using the `BrowseApi` you might also have been provided with `Tag` objects. In that case simply use `addTag` and pass in the `Tag` object instead of the address string.
+If you are using the `BrowseApi` you might also have been provided with `Tag` objects. In that case simply use `add_tag` and
+pass in the `PlcTag` object instead of the address string.
The request is sent to the PLC by issuing the `execute` method on the request object:
@@ -120,7 +122,8 @@ except ...
----
In general, all requests are executed asynchronously.
-As soon as the request is fully processed, the callback gets called and will contain a `ReadResponse`, if everything went right or an excception if there were problems.
+As soon as the request is fully processed, the callback gets called and will contain a `ReadResponse`, if everything went right or
+an excception if there were problems.
The following example will demonstrate some of the options you have:
@@ -143,7 +146,8 @@ for tag_name in response.tag_names:
----
In the for-loop, we are demonstrating how the user can iterate over the tag aliases in the response.
-In case of an ordinary read request, this will be predefined by the items in the request, however in case of a subscription response, the response might only contain some of the items that were subscribed.
+In case of an ordinary read request, this will be predefined by the items in the request, however in case of a subscription
+response, the response might only contain some of the items that were subscribed.
Before accessing the data, it is advisable to check if an item was correctly returned.
This is done by the `response_code` property for a given alias.
@@ -158,12 +162,13 @@ If this is `PlcResponseCode.OK`, everything is ok, however it could be one of th
Assuming the return code was `OK`, we can continue accessing the data.
-As all PlcValue items support the len property, the user can check how many items of a given type are returned by calling len(response.tags[tag_name].value)
+As all PlcValue items support the len property, the user can check how many items of a given type are returned
+by calling len(response.tags[tag_name].value)
You can then treat the values in the PlcList as a list using response.tags[tag_name].value.get_list()
-==== Writing Data
+=== Writing Data
In general the structure of code for writing data is extremely similar to that of reading data.
@@ -173,7 +178,7 @@ So first it is advisable to check if this connection is even able to write data:
// Check if this connection support writing of data.
if not plc_connection.is_write_supported():
logger.error("This connection doesn't support writing.")
- return
+
----
As soon as we are sure that we can write, we create a new `PlcWriteRequest.Builder`:
@@ -183,8 +188,8 @@ As soon as we are sure that we can write, we create a new `PlcWriteRequest.Build
// - Give the single item requested an alias name
// - Pass in the data you want to write (for arrays, pass in a list of values)
with connection.write_request_builder() as builder:
- builder.add_item("Random Tag 1", "4x00001[2]", [1, 2])
- builder.add_item("Random Tag 2", "4x00011", 1)
+ builder.add_item("Random Tag 1", "4x00001[2]", PlcList([PlcINT(1), PlcINT(2)]))
+ builder.add_item("Random Tag 2", "4x00011", PlcINT(1))
request = builder.build()
----
@@ -210,6 +215,6 @@ for tag_name in response.tag_names:
logger.error("Error[" + tag_name + "]: " + response.tags[tag_name].name())
----
-==== Subscribing to Data
+=== Subscribing to Data
Coming Soon
diff --git a/src/site/asciidoc/users/getting-started/using-snapshots.adoc b/src/site/asciidoc/users/getting-started/using-snapshots.adoc
index b6a29a126d8..3044ef838b8 100644
--- a/src/site/asciidoc/users/getting-started/using-snapshots.adoc
+++ b/src/site/asciidoc/users/getting-started/using-snapshots.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Using SNAPSHOT versions
+= Using SNAPSHOT versions
Especially when it comes to trying to verify if an issue you are facing has already been fixed in the development version, you might want to or be asked to try out the absolute latest version of PLC4X. You can generally do this by adding "-SNAPSHOT" to the version number of PLC4X.
diff --git a/src/site/asciidoc/users/getting-started/virtual-modbus.adoc b/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
index 5da29851b7b..8aa9b815e60 100644
--- a/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
+++ b/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
@@ -16,7 +16,7 @@
//
:imagesdir: ../../images/
-== Playing around with Apache PLC4X with a virtual Modbus PLC
+= Playing around with Apache PLC4X with a virtual Modbus PLC
If you want to get started with Apache PLC4X, but don't have any PLC at hand, this tutorial will demonstrate how you can use a virtual `Modbus Slave` software to simulate communication with `Modbus` enabled PLCs.
@@ -24,7 +24,7 @@ Such a fully open-source software is `ModbusPal` which is available from http://
All you need, is to download the file called `ModbusPal.jar`.
-=== Setting up the virtual Modbus Slave
+== Setting up the virtual Modbus Slave
In order to run the software, you just need to execute the following command in the same directory you downloaded the Jar to:
diff --git a/src/site/asciidoc/users/index.adoc b/src/site/asciidoc/users/index.adoc
index 53694a20227..004459b733b 100644
--- a/src/site/asciidoc/users/index.adoc
+++ b/src/site/asciidoc/users/index.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../images/
:icons: font
-== Users
+= Users
This part of the PLC4X website is dedicated to people wanting to use Apache PLC4X.
diff --git a/src/site/asciidoc/users/industry40.adoc b/src/site/asciidoc/users/industry40.adoc
index a918c8cbd3d..5c6243df457 100644
--- a/src/site/asciidoc/users/industry40.adoc
+++ b/src/site/asciidoc/users/industry40.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Industry 4.0 with Apache
+= Industry 4.0 with Apache
Since the introduction of programmable logic controllers in the production industry in the early 80s, they have been the core of almost every piece of production machinery.
@@ -32,7 +32,7 @@ Most of the biggest changes in how we create modern IT systems is a result of th
Unfortunately the production industry has been missing a lot of this innovation.
Only a small number of companies today use open source software in their production systems.
-=== Benefits of using open source
+== Benefits of using open source
The benefit of using open source could be huge:
@@ -42,21 +42,21 @@ The benefit of using open source could be huge:
* Improved Security
* Great Cost reduction
-==== Increased Flexibility
+=== Increased Flexibility
If a company had decided to use PLCs and control systems of a certain vendor, it is almost impossible to change this decision.
This reduces the options available when adding new machinery or replacing existing ones.
Technologically speaking, also the company can only use the options and solution it's vendor is able to provide.
-==== Increased Stability
+=== Increased Stability
Current control systems are usually based on the concept of "backup systems".
If the main control system fails, all activity is switched to the standby system.
When using modern public- or private cloud systems, there is no need for a backup system, because the cluster is designed in a way that it can live with the failure of most of its hosts before loosing the ability to function.
-==== Increased Extendability
+=== Increased Extendability
From the perspective of designing and scaling the IT infrastructure:
If a control system was designed to handle the current size of plant, for cost reasons the IT infrastructure isn't designed to handle much more than that.
@@ -65,14 +65,14 @@ Now if the plant should be extended in the future, extending it's control-system
By utilizing modern virtualization frameworks, extending the existing cloud solution, would only require adding more compute resources, by adding more systems to the cluster and it should be possible to extend the existing system without problems.
If the company decided to utilize a public cloud provider, it makes things even simpler, as it would only require booking more resources.
-==== Improved Security
+=== Improved Security
This is probably one of the most concerning aspects of modern production control systems.
Right now, in order to run these systems, a lot of the most popular solutions require companies to run not up to date systems.
If applying all updates, the company is risking either loss of commercial support or even loss of functionality.
Therefore an attacker can probably be certain to be able to exploit certain vulnerabilities just by knowing the type and version of the used control system.
-==== Cost Reduction
+=== Cost Reduction
Well the probably biggest and most obvious cost reduction factor is definitely, that if the software you are using is free, you will not have to pay for it.
@@ -80,7 +80,7 @@ Additionally, the ability to get the computing power of one insanely expensive s
Being freed of the requirement to stick to the products of one vendor alone and to be able to choose the technology and the vendor of used systems freely will definitely also reduce costs.
-=== Options to communicating with PLCs
+== Options to communicating with PLCs
In general there are two options for communicating with industrial PLCs:
diff --git a/src/site/asciidoc/users/integrations/apache-calcite.adoc b/src/site/asciidoc/users/integrations/apache-calcite.adoc
index e8a37d02ea7..83c0d31c21c 100644
--- a/src/site/asciidoc/users/integrations/apache-calcite.adoc
+++ b/src/site/asciidoc/users/integrations/apache-calcite.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Apache Calcite
+= Apache Calcite
https://calcite.apache.org/[Apache Calcite]
Standard SQL
diff --git a/src/site/asciidoc/users/integrations/apache-camel.adoc b/src/site/asciidoc/users/integrations/apache-camel.adoc
index b65f751ef99..31e0026e70e 100644
--- a/src/site/asciidoc/users/integrations/apache-camel.adoc
+++ b/src/site/asciidoc/users/integrations/apache-camel.adoc
@@ -17,6 +17,6 @@
:imagesdir: ../../images/
:icons: font
-== Apache Camel
+= Apache Camel
The Camel Component for PLC4X allows you to create routes using the PLC4X API to read from a PLC device or write to it.
This component is now maintained within the https://camel.apache.org/components/next/plc4x-component.html[Apache Camel] Project.
diff --git a/src/site/asciidoc/users/integrations/apache-edgent.adoc b/src/site/asciidoc/users/integrations/apache-edgent.adoc
index bfc713e1c4f..3c90fb4ab43 100644
--- a/src/site/asciidoc/users/integrations/apache-edgent.adoc
+++ b/src/site/asciidoc/users/integrations/apache-edgent.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/
:icons: font
-== Apache Edgent (Retired)
+= Apache Edgent (Retired)
diff --git a/src/site/asciidoc/users/integrations/apache-iotdb.adoc b/src/site/asciidoc/users/integrations/apache-iotdb.adoc
index 8c069968098..5e1a431f637 100644
--- a/src/site/asciidoc/users/integrations/apache-iotdb.adoc
+++ b/src/site/asciidoc/users/integrations/apache-iotdb.adoc
@@ -17,13 +17,13 @@
:imagesdir: ../../images/
:icons: font
-== Apache IotDB
+= Apache IotDB
Apache IoTDB is database for storing time serie data.
Therefore, it can be a good solution for managing the data which is collected by PLC4x.
-=== Data Model (Concept)
+== Data Model (Concept)
Given a PLC address and some fields, we can consider the PLC as a `device` in IoTDB, and each field
as a `measurement` in IoTDB. A couple of PLCs form a `storage group`.
@@ -32,7 +32,7 @@ For example, there is a virtual storage group `mi`, and a PLC `d1`, which has on
Then, in IoTDB, we can get a time series like `root.mi.d1.foo` (or `root.mi.d1.RANDOM_foo_Integer`, as you like).
Then, we can write data into IoTDB using JDBC with SQL or native API called session API.
-=== Example
+== Example
https://github.com/apache/plc4x-extras/tree/develop/plc4j/examples/hello-integration-iotdb shows an example
to collect data using PLC4x and then writing data to IoTDB.
diff --git a/src/site/asciidoc/users/integrations/apache-kafka.adoc b/src/site/asciidoc/users/integrations/apache-kafka.adoc
index 6a0a244573f..00469f8882f 100644
--- a/src/site/asciidoc/users/integrations/apache-kafka.adoc
+++ b/src/site/asciidoc/users/integrations/apache-kafka.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== https://kafka.apache.org/[Apache Kafka]
+= https://kafka.apache.org/[Apache Kafka]
Apache Kafka is an open-source distributed event streaming platform used by thousands of
companies for high-performance data pipelines, streaming analytics, data integration, and
diff --git a/src/site/asciidoc/users/integrations/apache-nifi.adoc b/src/site/asciidoc/users/integrations/apache-nifi.adoc
index abe7bd365dd..97ba3709577 100644
--- a/src/site/asciidoc/users/integrations/apache-nifi.adoc
+++ b/src/site/asciidoc/users/integrations/apache-nifi.adoc
@@ -17,13 +17,13 @@
:imagesdir: ../../images/
:icons: font
-== Apache NiFi
+= Apache NiFi
Apache NiFi allows creating systems that process data around the concept of data-streams.
Apache PLC4X provides both `Source` as well as `Sink` processors for accessing data in PLCs or writing data to them.
-=== Setting Up NiFi
+== Setting Up NiFi
Even if the documentation of NiFi states it works with any Java version above 1.8, this is not quite true.
@@ -40,7 +40,7 @@ As soon as you have started NiFi using the `nifi.sh run` or `run-nifi.bat` the W
It might take a few seconds for the Web-UI to show up ... so if you're getting errors in the browser, give it some time to start.
====
-=== Enabling PLC4X Processors in NiFi
+== Enabling PLC4X Processors in NiFi
In order to enable `Apache PLC4X` support in `Apache NiFi` all you need to do, is to copy our `nar` archive into the Nifi installations `lib` directory.
@@ -50,7 +50,7 @@ Or you can download a released version from Maven central: https://search.maven.
image::integrations/nifi/empty-nifi-flow.png[]
-=== Using a PLC4X Source Processor in NiFi
+== Using a PLC4X Source Processor in NiFi
Add a PLC4X Source processor to the canvas, click on the `Add processor` button and drag it into the canvas.
@@ -136,7 +136,7 @@ Now you should see an increasing number at the `Out` of the PLC4X Source and on
image::integrations/nifi/running-flow.png[]
-=== Enabling debugging
+== Enabling debugging
In order to be able to debug the PLC4X, please edit the `bin/nifi.sh` (On Mac & Linux) and comment in the line:
diff --git a/src/site/asciidoc/users/integrations/apache-streampipes.adoc b/src/site/asciidoc/users/integrations/apache-streampipes.adoc
index 7bf1ae05a9d..4e854529194 100644
--- a/src/site/asciidoc/users/integrations/apache-streampipes.adoc
+++ b/src/site/asciidoc/users/integrations/apache-streampipes.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Apache StreamPipes
+= Apache StreamPipes
https://streampipes.apache.org/docs/pe/org.apache.streampipes.connect.iiot.adapters.plc4x.s7[PLC4X S7 Adapter,opts=nofollow]
diff --git a/src/site/asciidoc/users/integrations/eclipse-ditto.adoc b/src/site/asciidoc/users/integrations/eclipse-ditto.adoc
index 4413b819820..e70e744225d 100644
--- a/src/site/asciidoc/users/integrations/eclipse-ditto.adoc
+++ b/src/site/asciidoc/users/integrations/eclipse-ditto.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Eclipse Ditto
+= Eclipse Ditto
… where IoT devices and their digital twins get together
https://www.eclipse.org/ditto/
diff --git a/src/site/asciidoc/users/integrations/eclipse-milo.adoc b/src/site/asciidoc/users/integrations/eclipse-milo.adoc
index 6107c9d82f9..33b0b42557e 100644
--- a/src/site/asciidoc/users/integrations/eclipse-milo.adoc
+++ b/src/site/asciidoc/users/integrations/eclipse-milo.adoc
@@ -15,12 +15,12 @@
// limitations under the License.
//
-== Introduction
+= Introduction
The PLC4X OPC UA server integration is based around the Eclipse Milo OPC UA server. It uses PLC4X to communicate with
industrial devices effectively acting as a industrial OPC UA gateway.
-== Building the server
+= Building the server
The OPC UA server can be built using maven as part of the PLC4X build.
```
@@ -30,7 +30,7 @@ mvn install
This creates a target directory within plc4x/plc4j/integrations/opcua-server containing a jar file which is the main java
executable.
-== Configuration File
+= Configuration File
The config.yml file is used to configure the server. The following root level settings should be configured.
@@ -93,7 +93,7 @@ tcpPort: 12687
httpPort: 8445
```
-== Running
+= Running
To run the java executable execute:-
```
diff --git a/src/site/asciidoc/users/integrations/index.adoc b/src/site/asciidoc/users/integrations/index.adoc
index f9ac3beba90..6e50951096b 100644
--- a/src/site/asciidoc/users/integrations/index.adoc
+++ b/src/site/asciidoc/users/integrations/index.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/
:icons: font
-== Integrations
+= Integrations
diff --git a/src/site/asciidoc/users/issues.adoc b/src/site/asciidoc/users/issues.adoc
index 13b44a1f377..1000e363e31 100644
--- a/src/site/asciidoc/users/issues.adoc
+++ b/src/site/asciidoc/users/issues.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Bug & Issue Tracker
+= Bug & Issue Tracker
Our bug & issue tracker is Github-Issues.
diff --git a/src/site/asciidoc/users/preparing-issues.adoc b/src/site/asciidoc/users/preparing-issues.adoc
index 1a73e204c7a..e94365f7f8f 100644
--- a/src/site/asciidoc/users/preparing-issues.adoc
+++ b/src/site/asciidoc/users/preparing-issues.adoc
@@ -15,5 +15,5 @@
// limitations under the License.
//
-== Preparing Issues & Bug Reports
+= Preparing Issues & Bug Reports
diff --git a/src/site/asciidoc/users/protocols/ab-eth.adoc b/src/site/asciidoc/users/protocols/ab-eth.adoc
index 391fea2b361..23a8c9583e7 100644
--- a/src/site/asciidoc/users/protocols/ab-eth.adoc
+++ b/src/site/asciidoc/users/protocols/ab-eth.adoc
@@ -17,8 +17,8 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== AB-ETH
+= AB-ETH
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/ab-eth.adoc[]
diff --git a/src/site/asciidoc/users/protocols/ads.adoc b/src/site/asciidoc/users/protocols/ads.adoc
index db3aedcc3d1..44162573819 100644
--- a/src/site/asciidoc/users/protocols/ads.adoc
+++ b/src/site/asciidoc/users/protocols/ads.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== ADS (Automation Device Specification)
+= ADS (Automation Device Specification)
image::ads_banner.png[banner,512,167]
The ADS (automation device specification) describes a device-independent and fieldbus independent interface for communication between Beckhoff automation devices running TwinCAT and other devices implementing this interface. https://www.home-assistant.io/integrations/ads/ Source (accessed 7 August 2022)
@@ -26,13 +26,13 @@ ADS device concept: https://infosys.beckhoff.com/english.php?content=../content/
Specification for ADS devices: https://infosys.beckhoff.com/english.php?content=../content/1033/ams_nat/4275563275.html&id= Source (accessed 7 August 2022)
-=== Structure AMS/TCP Packet
+== Structure AMS/TCP Packet
ADS (Automation Device Specification) is the TwinCAT communication protocol that specifies the interaction between two ADS devices. For example, it defines what operations can be executed on another ADS device, what parameters are necessary for that and what return value is sent after execution.
AMS (Automation Message Specification) specifies the exchange of the ADS data. A major component of the communication protocol is the AmsNetId. This is specified in the AMS/ADS package for the source and target device. An ADS device can be explicitly addressed using the AmsNetId.
Source https://infosys.beckhoff.com/english.php?content=../content/1033/ams_nat/4275563275.html&id= (accessed 7 August 2022)
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/ads.adoc[]
@@ -56,7 +56,7 @@ include::../../../plc4j/drivers/all/src/site/generated/ads.adoc[]
|===
-=== More details on
+== More details on
For details about the protocol look here: http://www.beckhoff.com/
& (German Handbook: https://download.beckhoff.com/download/Document/automation/twincat3/TwinCAT_3_ADS_INTRO_DE.pdf)
diff --git a/src/site/asciidoc/users/protocols/bacnet.adoc b/src/site/asciidoc/users/protocols/bacnet.adoc
index e49888e3ab1..b05a3d87f53 100644
--- a/src/site/asciidoc/users/protocols/bacnet.adoc
+++ b/src/site/asciidoc/users/protocols/bacnet.adoc
@@ -17,13 +17,13 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== BACnet/IP
+= BACnet/IP
image::bacnet_banner.png[banner,512,167]
-=== BACnet (Building Automation and Control Networks)
+== BACnet (Building Automation and Control Networks)
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/bacnet-ip.adoc[]
@@ -47,6 +47,6 @@ include::../../../plc4j/drivers/all/src/site/generated/bacnet-ip.adoc[]
|===
-=== More details on
+== More details on
http://www.bacnet.org/[BACnet - A Data Communication Protocol for Building Automation and Control Networks]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/c-bus.adoc b/src/site/asciidoc/users/protocols/c-bus.adoc
index a2ddbbd3450..478c65c1f11 100644
--- a/src/site/asciidoc/users/protocols/c-bus.adoc
+++ b/src/site/asciidoc/users/protocols/c-bus.adoc
@@ -17,8 +17,8 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== C-Bus
+= C-Bus
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/c-bus.adoc[]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/can.adoc b/src/site/asciidoc/users/protocols/can.adoc
index 062dbaa2c98..159be9ec10a 100644
--- a/src/site/asciidoc/users/protocols/can.adoc
+++ b/src/site/asciidoc/users/protocols/can.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== CAN Bus Driver Adapter
+= CAN Bus Driver Adapter
image::can_banner.png[banner,512,167]
@@ -25,7 +25,7 @@ The CAN Bus driver is a special kind of driver which does not bring any logic.
Its responsibility is to combine link:../transports/can.html[CAN transport facade] and custom application layer protocols.
In this way, the protocol can use its own "root frame" type which is not delivered from CAN bus frame.
-=== More details on the driver
+== More details on the driver
The `CANDriverAdapter` is a full implementation of Apache PLC4X API.
Under the hood adapter will forward all operations to delegate driver.
diff --git a/src/site/asciidoc/users/protocols/canopen.adoc b/src/site/asciidoc/users/protocols/canopen.adoc
index 1f7345f0a7c..ee4ad82a3c8 100644
--- a/src/site/asciidoc/users/protocols/canopen.adoc
+++ b/src/site/asciidoc/users/protocols/canopen.adoc
@@ -17,13 +17,14 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== CANopen
+= CANopen
image::can_banner.png[banner,512,167]
-=== CAN in Automation
+
+== CAN in Automation
CANopen is a specific protocol built on top of CAN bus.
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/canopen.adoc[]
@@ -46,7 +47,7 @@ include::../../../plc4j/drivers/all/src/site/generated/canopen.adoc[]
- It is possible to subscribe to CANopen NMT messages.
|===
-=== More details on the driver
+== More details on the driver
CAN, despite (or due) to its popularity has ambiguous meaning.
There are multiple articles and sources which attempts to give introduction, yet very few of them is consistent between each other.
@@ -75,7 +76,7 @@ The CANopen specification defines Object Dictionary (OD).
This driver does honor OD structure through usage of index and sub index for addressing fields.
It does not ship Electronic Data Sheet (EDS) parser leaving it for applications who wish to utilize it.
-=== Address Format
+== Address Format
CANopen specification defines several groups of addresses dedicated to certain kind of operations.
Critical services and message exchanges related with them have lower identifiers making them wining eventual bus access.
diff --git a/src/site/asciidoc/users/protocols/ctrlx.adoc b/src/site/asciidoc/users/protocols/ctrlx.adoc
index 872b743a66e..e89db5f0eeb 100644
--- a/src/site/asciidoc/users/protocols/ctrlx.adoc
+++ b/src/site/asciidoc/users/protocols/ctrlx.adoc
@@ -17,8 +17,8 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== CtlrX
+= CtlrX
-=== Connection String Options
+== Connection String Options
//include::../../../plc4j/drivers/all/src/site/generated/ctrlx.adoc[]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/deltav.adoc b/src/site/asciidoc/users/protocols/deltav.adoc
index 2d3298de94c..456487d70a3 100644
--- a/src/site/asciidoc/users/protocols/deltav.adoc
+++ b/src/site/asciidoc/users/protocols/deltav.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== DeltaV
+= DeltaV
diff --git a/src/site/asciidoc/users/protocols/df1.adoc b/src/site/asciidoc/users/protocols/df1.adoc
index c93ff1d90e2..19e04d7b84b 100644
--- a/src/site/asciidoc/users/protocols/df1.adoc
+++ b/src/site/asciidoc/users/protocols/df1.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== DF1
+= DF1
diff --git a/src/site/asciidoc/users/protocols/eip.adoc b/src/site/asciidoc/users/protocols/eip.adoc
index f7bc9978792..0ae30b47d0d 100644
--- a/src/site/asciidoc/users/protocols/eip.adoc
+++ b/src/site/asciidoc/users/protocols/eip.adoc
@@ -17,13 +17,13 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== EtherNet/IP
+= EtherNet/IP
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/eip.adoc[]
-=== Address Format
+== Address Format
To read and write data to a PLC4X device, the EtherNet/IP driver uses symbolic segments.
This is used to refer to objects through their symbolic names. This makes reading data a lot easier, as you do not
@@ -44,7 +44,7 @@ To read and write data to a PLC4X device, the EtherNet/IP driver uses symbolic s
|DataType (writing) |Specify the Data-type of the value you want to write (mandatory)
|===
-==== Data Types
+=== Data Types
[cols="2" ,options="header"]
|===
|To store a|Use this data type
diff --git a/src/site/asciidoc/users/protocols/firmata.adoc b/src/site/asciidoc/users/protocols/firmata.adoc
index dea5f9ec21a..42ef1c9601b 100644
--- a/src/site/asciidoc/users/protocols/firmata.adoc
+++ b/src/site/asciidoc/users/protocols/firmata.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Firmata
+= Firmata
The Firmata protocol is based on the MIDI protocol used for communicating with musical equipment.
@@ -25,7 +25,7 @@ It is also one of the most widely used protocols for communication with Arduino
This driver is built to be compatible with the `StandardFirmata Arduino Sketch` which can be found https://github.com/firmata/arduino/blob/master/examples/StandardFirmata/StandardFirmata.ino[here] (Version last changed on August 17th, 2017)
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/firmata.adoc[]
@@ -46,13 +46,13 @@ include::../../../plc4j/drivers/all/src/site/generated/firmata.adoc[]
NOTE: When subscribing to pins, these are configured to become read pins. When writing to digital pins, these are configured to become output pins. However, writing to pins for which a subscription exists, an exception will be thrown. In order to write to previously subscribed pins, all subscriptions for this have to be cancelled first.
-=== Individual Resource Address Format
+== Individual Resource Address Format
Similar to the Modbus protocol, the Firmata protocol support Boolean and Short values.
Booleans are used for the digital IO pins and short values for the analog inputs.
-==== Binary Addresses
+=== Binary Addresses
The full format for a digital address has the following format:
@@ -77,7 +77,7 @@ A normal `Arduino Uno` is equipped with 14 digital inputs: 0-13
WARNING: However in case of using the serial port (which will always be the case when using this driver), the pins 0 and 1 are the `RX` and `TX` pins of the serial port and can't be used.
-==== Analog Addresses
+=== Analog Addresses
The full format for an analog address is as follows:
diff --git a/src/site/asciidoc/users/protocols/genericcan.adoc b/src/site/asciidoc/users/protocols/genericcan.adoc
index 5633f2751f8..da07b93742a 100644
--- a/src/site/asciidoc/users/protocols/genericcan.adoc
+++ b/src/site/asciidoc/users/protocols/genericcan.adoc
@@ -17,16 +17,16 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Generic CAN
+= Generic CAN
-=== CAN Bus semantics
+== CAN Bus semantics
This driver is a generic purpose driver.
It allows implementing a basic CAN bus listening or writing scenarios.
CAN bus open is a specific protocol built on top of CAN bus.
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/genericcan.adoc[]
@@ -46,7 +46,7 @@ include::../../../plc4j/drivers/all/src/site/generated/genericcan.adoc[]
|===
-=== More details on the driver
+== More details on the driver
Given popularity of CAN in multiple market segments there is variety of protocols which can't be published.
Also, for many cases which are data acquisition oriented it is necessary to tap only parts of communications.
@@ -55,7 +55,7 @@ This driver allows to model incoming and outgoing communication using plain Apac
The written CAN data is constructed from fields submitted via write request builder.
The receiving data is transformed in similar fashion, based on subscribed fields.
-==== Address format
+=== Address format
[cols="1,1a,1a,2a"]
|===
diff --git a/src/site/asciidoc/users/protocols/iec-60870.adoc b/src/site/asciidoc/users/protocols/iec-60870.adoc
index 5a87891f45c..747c79cf4a1 100644
--- a/src/site/asciidoc/users/protocols/iec-60870.adoc
+++ b/src/site/asciidoc/users/protocols/iec-60870.adoc
@@ -17,8 +17,8 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== IEC-60870
+= IEC-60870
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/iec-60870-5-104.adoc[]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/index.adoc b/src/site/asciidoc/users/protocols/index.adoc
index 5ad3536941c..4af0ec637fc 100644
--- a/src/site/asciidoc/users/protocols/index.adoc
+++ b/src/site/asciidoc/users/protocols/index.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Current language support for protocols
+= Current language support for protocols
:icons: font
|===
|Protocol | C | C# | Go | Java | Python
@@ -153,6 +153,13 @@
|icon:check[role="green"]
|icon:times[role="red"]
+|UMAS
+|icon:times[role="red"]
+|icon:times[role="red"]
+|icon:times[role="red"]
+|icon:times[role="red"]
+|icon:check[role="green"]
+
|===
Legend:
@@ -162,7 +169,7 @@ Legend:
- icon:check[role="red"] Not implemented yet
- icon:question[role="red"] Unsure
-== Features
+= Features
:icons: font
The following table contains a list of operations and the protocols that support them:
@@ -379,6 +386,17 @@ The following table contains a list of operations and the protocols that support
|icon:question[role="red"]
|icon:question[role="red"]
+|UMAS
+|icon:question[role="red"]
+|icon:question[role="red"]
+|icon:check[role="green"]
+|icon:check[role="green"]
+|icon:check[role="green"]
+|icon:question[role="red"]
+|icon:question[role="red"]
+|icon:question[role="red"]
+|icon:question[role="red"]
+
|===
Legend:
diff --git a/src/site/asciidoc/users/protocols/knxnetip.adoc b/src/site/asciidoc/users/protocols/knxnetip.adoc
index 84d465031e7..4e2522668a9 100644
--- a/src/site/asciidoc/users/protocols/knxnetip.adoc
+++ b/src/site/asciidoc/users/protocols/knxnetip.adoc
@@ -17,14 +17,14 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== KNXnet/IP
+= KNXnet/IP
image::knx_banner.png[banner,512,167]
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/knxnet-ip.adoc[]
-=== Individual Resource Address Format
+== Individual Resource Address Format
KNX Addresses usually have one of the following structures:
diff --git a/src/site/asciidoc/users/protocols/logix.adoc b/src/site/asciidoc/users/protocols/logix.adoc
index db60c5f32dd..77458b6b63b 100644
--- a/src/site/asciidoc/users/protocols/logix.adoc
+++ b/src/site/asciidoc/users/protocols/logix.adoc
@@ -17,15 +17,15 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Logix
+= Logix
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/logix.adoc[]
-=== Individual Resource Address Format
+== Individual Resource Address Format
-==== Connection String
+=== Connection String
Logix has the following connection string format:-
----
@@ -38,7 +38,7 @@ logix:tcp://127.0.0.1:502?communicationPath=[1,1]
Note the port and option fields are optional.
-==== General Format
+=== General Format
In general all Logix addresses have this format:
@@ -50,7 +50,7 @@ If the array-size part is omitted, the size-default of `1` is assumed.
If the data-type part is omitted, the data type from the controller is used
The address format matches that found in the controller.
-==== Data Types
+=== Data Types
The following data types are supported
diff --git a/src/site/asciidoc/users/protocols/modbus.adoc b/src/site/asciidoc/users/protocols/modbus.adoc
index 5f210f50c65..4c0d2bd46bc 100644
--- a/src/site/asciidoc/users/protocols/modbus.adoc
+++ b/src/site/asciidoc/users/protocols/modbus.adoc
@@ -17,23 +17,23 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Modbus (TCP/UDP/Serial)
+= Modbus (TCP/UDP/Serial)
-=== Connection String Options
+== Connection String Options
-==== Modbus TCP
+=== Modbus TCP
include::../../../plc4j/drivers/all/src/site/generated/modbus-tcp.adoc[]
-==== Modbus RTU
+=== Modbus RTU
include::../../../plc4j/drivers/all/src/site/generated/modbus-rtu.adoc[]
-==== Modbus ASCII
+=== Modbus ASCII
include::../../../plc4j/drivers/all/src/site/generated/modbus-ascii.adoc[]
-=== Supported Operations
+== Supported Operations
[cols="2,2a,5a"]
|===
@@ -48,9 +48,9 @@ include::../../../plc4j/drivers/all/src/site/generated/modbus-ascii.adoc[]
2+| `write`
|===
-=== Individual Resource Address Format
+== Individual Resource Address Format
-==== Connection String
+=== Connection String
Modbus has the following connection string format:-
----
@@ -63,7 +63,7 @@ modbus-tcp:tcp://127.0.0.1:502
Note the transport, port and option fields are optional.
-==== General Format
+=== General Format
In general all Modbus addresses have this format:
@@ -86,7 +86,7 @@ Specifying this value overrides value of `default-unit-id` parameter specified a
----
With this, can the default byte-order be overridden on a per-tag basis. If not provided the default-byte-order from the connection string is used, or BIG_ENDIAN, if this is also not provided.
-==== Memory Areas
+=== Memory Areas
There are a number of memory areas defined in the Modbus specification.
@@ -120,7 +120,7 @@ Address 610000 is then the first address in the second file record and so on. It
Using the extended-register: format you are able to reference all of these, if the shorter format is used then it is limited to 699999.
This memory area starts at address 0.
-==== Data Types
+=== Data Types
The following data types are supported
@@ -142,7 +142,7 @@ The following data types are supported
- CHAR (char)
- WCHAR (2 byte char)
-==== Some useful tips
+=== Some useful tips
Most memory areas start at address 1, except for the extended register area which starts at 0. These are both mapped to 0x0000 when it is sent in the Modbus protocol.
@@ -161,7 +161,7 @@ The following Modbus function codes are supported:-
- 0x14 (Read File Record)(Extended Register Read)
- 0x15 (Write File Record)(Extended Register Write)
-==== Examples
+=== Examples
To read 10 holding registers starting at address 20 and parse as Unsigned Integers the following examples are all valid.
diff --git a/src/site/asciidoc/users/protocols/opcua.adoc b/src/site/asciidoc/users/protocols/opcua.adoc
index 4116697e745..dd5bc8dc469 100644
--- a/src/site/asciidoc/users/protocols/opcua.adoc
+++ b/src/site/asciidoc/users/protocols/opcua.adoc
@@ -17,9 +17,9 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== OPC UA
+= OPC UA
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/opcua.adoc[]
@@ -34,7 +34,7 @@ include::../../../plc4j/drivers/all/src/site/generated/opcua.adoc[]
|===
-=== Connection String
+== Connection String
The OPC UA drivers uses the connection string
@@ -54,7 +54,7 @@ opcua:tcp://127.0.0.1:12686?discovery=true&username=admin&password=password
Note the transport, port and options fields are optional.
-=== Secure communication
+== Secure communication
The secure channel implementation within Apache PLC4X project have been tested against existing open source server implementations.
This includes Eclipse Milo (all modes) as well as OPC Foundation .NET server (except `Basic128Rsa15`).
Manual tests proven that driver is able to communicate with OPC UA server launched on PLCs as well as commercial simulators.
@@ -69,7 +69,7 @@ By default, this option is set to `SIGN_ENCRYPT` which imposes high security set
In case when additional diagnostics is needed payloads has to be traced through TRACE level log entries.
The `SIGN` mode gives possibility o browse packets in tools such wireshark.
-==== Certificate verification
+=== Certificate verification
The OPC UA specification defines its own procedures for certificate validation.
In order to simplify implementation by default server certificate validation is relaxed.
Unless explicitly disabled through configuration of `trustStoreFile` all server certificates will be accepted without validation.
@@ -77,7 +77,7 @@ Unless explicitly disabled through configuration of `trustStoreFile` all server
In case when secure communication is enabled the `trustStoreFile` option might be used to point certificates which client should accept.
The acceptance rely on regular TLS checks (expiry date, certificate path etc.), does not validate OPC UA specific parts such as application URI.
-==== Negotiation procedure
+=== Negotiation procedure
Depending on settings driver might or might not attempt to discover endpoints from remote server.
In case when `discovery` option is set to `true` driver will look up server certificate through connection attempt.
The discovery option also enables checks of server endpoints for matching security settings.
@@ -94,7 +94,7 @@ Usual values of `sendBufferSize` and `receiveBufferSize` PLC devices remain at 8
NOTE: Due to lack of complete implementation of negotiation and chunking logic the OPC UA driver prior Apache PLC4X 0.11 release could supply calls exceeding server limits.
-=== Address Format
+== Address Format
To read, write and subscribe to data, the OPC UA driver uses the variable declaration string of the OPC UA server it is
connecting to.
It includes the namespace(`ns`) of the hierarchy tree followed by the type of identifier string(`s`), numeric(`i`),
@@ -107,7 +107,7 @@ ns={namespace-index};[s|i|g|b]={Identifier};{Data Type}
----
-==== Data Types
+=== Data Types
The following data types are supported
@@ -132,7 +132,7 @@ The following data types are supported
- WSTRING (utf-16)
-==== Example of a valid OPC UA address:
+=== Example of a valid OPC UA address:
The following are examples of valid addresses
@@ -154,12 +154,12 @@ ns=2;g=09087e75-8e5e-499b-954f-f2a8624db28a;REAL
Note the Identifiers `s`,`i`,`b` and `g` specify the format of the address not the data type of the returned value.
-=== Some useful tips
+== Some useful tips
The namespace (e.g. `ns=2`) within the address is specific to the server you are connecting to.
-=== More details on OPC UA
+== More details on OPC UA
https://opcfoundation.org/about/opc-technologies/opc-ua/[OPC UA]
The OPC Unified Architecture (UA), released in 2008, is a platform independent service-oriented architecture that integrates all the functionality of the individual OPC Classic specifications into one extensible framework.
diff --git a/src/site/asciidoc/users/protocols/open-protocol.adoc b/src/site/asciidoc/users/protocols/open-protocol.adoc
index e9d87225792..eec5bbd7092 100644
--- a/src/site/asciidoc/users/protocols/open-protocol.adoc
+++ b/src/site/asciidoc/users/protocols/open-protocol.adoc
@@ -17,8 +17,8 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Open-Protocol (Torque-Tools)
+= Open-Protocol (Torque-Tools)
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/open-protocol.adoc[]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/plc4x.adoc b/src/site/asciidoc/users/protocols/plc4x.adoc
index 82cda1c070c..8a765cbf9e8 100644
--- a/src/site/asciidoc/users/protocols/plc4x.adoc
+++ b/src/site/asciidoc/users/protocols/plc4x.adoc
@@ -17,13 +17,13 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== PLC4X (Proxy) (TCP)
+= PLC4X (Proxy) (TCP)
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/plc4x.adoc[]
-=== Connection String Options
+== Connection String Options
[cols="2,2a,5a"]
|===
@@ -39,9 +39,9 @@ include::../../../plc4j/drivers/all/src/site/generated/plc4x.adoc[]
|===
-=== Individual Resource Address Format
+== Individual Resource Address Format
-==== Connection String
+=== Connection String
The `plc4x` protocol connection has the following connection string format:-
----
@@ -55,7 +55,7 @@ plc4x://127.0.0.1?remote-connection-string=simulated%3A%2F%2Flocalhost
Note the transport, port and option fields are optional.
The remote connection string: `simulated://localhost` is encoded as `simulated%3A%2F%2Flocalhost`
-==== General Format
+=== General Format
The address format is simply the address format of the used remote connection.
So if you specify a remote connection as `simulated`, please follow the address format of that driver.
\ No newline at end of file
diff --git a/src/site/asciidoc/users/protocols/profinet.adoc b/src/site/asciidoc/users/protocols/profinet.adoc
index dcecdf256ef..0239d2dd3a4 100644
--- a/src/site/asciidoc/users/protocols/profinet.adoc
+++ b/src/site/asciidoc/users/protocols/profinet.adoc
@@ -17,12 +17,12 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Profinet (In Development)
+= Profinet (In Development)
The PROFINET driver implements a class 3 real time controller. Which is able to communicate with multiple devices
on the same network segment.
-=== Connection String Options
+== Connection String Options
On linux as the Java executable won't have permission to capture raw packets, this needs to be enabled via:-
----
@@ -42,7 +42,7 @@ include::../../../plc4j/drivers/all/src/site/generated/profinet.adoc[]
|===
-=== Connection String
+== Connection String
The Profinet driver uses the connection string
@@ -66,7 +66,7 @@ profinet:raw://127.0.0.1?gsddirectory=/Profinet/GSD&devices=[[test-device-1,MOD_
Note the transport, port fields shouldn't have to be changed
-=== Address Format
+== Address Format
The format of address will be in the format.
----
@@ -83,7 +83,7 @@ device-1.1.1.DIGITAL_INPUT.0.1:BOOL
Note:-
-==== Data Types
+=== Data Types
The following data types are supported
@@ -108,7 +108,7 @@ The following data types are supported
- WSTRING (utf-16)
-=== Some useful tips
+== Some useful tips
Although the GSD file contains all the information needed to configure which data will be available from a device.
The easiest approach is to use the browsing function of the Profinet driver to return a list of all available tags.
diff --git a/src/site/asciidoc/users/protocols/s7.adoc b/src/site/asciidoc/users/protocols/s7.adoc
index 2acd668d43b..650a07a4b60 100644
--- a/src/site/asciidoc/users/protocols/s7.adoc
+++ b/src/site/asciidoc/users/protocols/s7.adoc
@@ -21,10 +21,10 @@
//:coderay-linenums-mode: inline
//:coderay-css: class
-== S7 (Step7)
+= S7 (Step7)
image::s7_banner.png[banner,512,167]
-=== Executive Summary
+== Executive Summary
This version of the S7 driver is aimed at exploiting the advanced features of the S7-300 and S7-400 controllers, as well as basic reading and writing functions for the S7-1200 and S7-1500 devices (PUT/GET functions). We hope in a short period of time to have the S7-Plus version, which should exploit the asynchronous functions of the S7-1500.
@@ -49,7 +49,7 @@ Although this driver is developed using Siemens Hardware, it should be functiona
NOTE: When trying to connect to a Siemens `LOGO` device, it is important to add one connection option, as Siemens seems to have only partially implemented the protocol, the device simply terminates the connection as soon as our driver tried to read the SZL table in order to find out which type of S7 device it is talking to. This can be disabled by passing in the type of PLC. For a Siemens LOGO device therefore please add `?controller-type=LOGO` to the connection string.
-=== Regarding the Support
+== Regarding the Support
It is typical within the decision-making cycle in an automation project to know who and how much the support of the tools that will be used in the control architecture will cost.
@@ -57,7 +57,7 @@ PLC4X support is on our development list (dev@plc4x.apache.org) where we will gl
If your company requires commercial support, companies that directly or indirectly support the drivers and tools developed in PLC4X are published on our page.
-=== Record of revisions made to the driver
+== Record of revisions made to the driver
[cols="1, 2,2a,5a"]
|===
@@ -67,9 +67,9 @@ If your company requires commercial support, companies that directly or indirect
|===
-=== Connecting as easy as 1-2-3.
+== Connecting as easy as 1-2-3.
-==== ONE
+=== ONE
In PLC4X the URL philosophy is used as the data source for the connection for the specification of the driver and its connection parameters, this is almost a standard in network applications (pointing to the best practices). It is also possible to create an instance of the driver directly and assign its parameters with the typical "set" methods.
@@ -89,7 +89,7 @@ image::s7_url.png[s7_url,,,,align="center"]
The SCHEMA and DOMAINE NAME are almost standard for any URL and do not require further explanation. The PARAMETERS that define the behavior of the driver are defined in the following table.
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/s7.adoc[]
@@ -114,7 +114,7 @@ include::../../../plc4j/drivers/all/src/site/generated/s7.adoc[]
|===
-==== TWO
+=== TWO
After defining the URL, the connection is made. Driver selection from the URL is done via PLC4X's SPI support, so driver instantiation and mapping originating from the URL is done transparently by the Java SPI services.
@@ -127,8 +127,8 @@ Any inconsistency in the URL definition will generate an exception that must be
.
.
try {
- PlcConnection connection = new DefaultPlcDriverManager().getConnection("s7://10.10.1.33?remote-rack=0&remote-slot=3&controller-type=S7_400"); //(2.1)
- final PlcReadRequest.Builder subscription = connection.readRequestBuilder(); //(2.2)
+ PlcConnection connection new DefaultPlcDriverManager().getConnection("s7://10.10.1.33?remote-rack=0&remote-slot=3&controller-type=S7_400"); //(2.1)
+ final PlcReadRequest.Builder subscription connection.readRequestBuilder(); //(2.2)
.
.
.
@@ -140,7 +140,7 @@ In (2.1) the driver instance is created, you only have to ensure that the requir
No problems? Then we are ready to configure and request the data that we require from the PLC. Let's go to step "three".
-==== THREE
+=== THREE
By having the connection we can start building and executing our requests.
@@ -151,9 +151,9 @@ By having the connection we can start building and executing our requests.
.
readrequest.addTagAddress("MySZL", "SZL_ID=16#0091;INDEX=16#0000"); //(3.1)
- final PlcReadRequest rr = readrequest.build(); //(3.2)
- final PlcReadResponse szlresponse = rr.execute().get(); //(3.3)
- if (szlresponse.getResponseCode("MySZL") == PlcResponseCode.OK) {//(3.4)
+ final PlcReadRequest rr readrequest.build(); //(3.2)
+ final PlcReadResponse szlresponse rr.execute().get(); //(3.3)
+ if (szlresponse.getResponseCode("MySZL") = PlcResponseCode.OK) {//(3.4)
}
.
.
@@ -168,13 +168,13 @@ These steps are shown separately for ease of analysis, but can be simplified int
A detailed explanation of the format for addressing PLCTags in the S7 driver will be given in the following sections.
-=== Individual Resource Address Format
+== Individual Resource Address Format
When programming Siemens PLCs, usually the tool used to do that is called TIA Portal.
The PLC4X S7 Driver is therefore sticking to the address format defined by this tool as it simplifies exchanging address information.
-==== General Format
+=== General Format
In general all S7 addresses have this format:
@@ -227,7 +227,7 @@ The shorter syntax looks like this:
The S7 driver will handle both types of notation equally.
-==== Memory Areas
+=== Memory Areas
The S7 driver currently allows access to the following memory areas.
@@ -286,7 +286,7 @@ Not all S7 device types support the same full set of memory areas, so the last c
|===
-==== Data Types
+=== Data Types
[cols="1,1,2,4,1,1"]
|===
@@ -330,7 +330,7 @@ Not all S7 device types support the same full set of memory areas, so the last c
-=== Actors participating in the communication process
+== Actors participating in the communication process
PLC programming in general is a Pandora's box!
@@ -369,7 +369,7 @@ endbox
. `CP`, the communications CP will depend on your architecture and requirements, for an S7-300 it will be a CP 343-1 or a CP 443-1 for an S7-400.
-==== S7 Read/Write
+=== S7 Read/Write
@@ -408,7 +408,7 @@ OS --> PLC4X
PLC4X --> App : to consumer
....
-==== S7 Event Subscription
+=== S7 Event Subscription
The S7 driver allows the subscription to asynchronous events generated in the PLC.
@@ -449,9 +449,9 @@ At the user application level `App`, you can use the PLC4X API to subscribe SCAN
In the following sections we will describe in more detail the functionalities of each field.
-==== SCAN Events
+=== SCAN Events
-==== Subscription to MODE events (S7ModeEvent).
+=== Subscription to MODE events (S7ModeEvent).
By subscribing to controller status changes or `MODE` events, the PLC status changes can be tracked.
@@ -528,19 +528,19 @@ With the sequence diagram and the data structures that will be received by the a
public class PLCEventModeSubscription {
public static void main(String[] args) throws Exception {
- try (PlcConnection connection = new PlcDriverManager()
+ try (PlcConnection connection new PlcDriverManager()
.getConnection("s7://192.168.1.51?remote-rack=0&remote-slot=3&controller-type=S7_400")) {
- final PlcSubscriptionRequest.Builder subscription = connection.subscriptionRequestBuilder(); // <01>
+ final PlcSubscriptionRequest.Builder subscription connection.subscriptionRequestBuilder(); // <01>
subscription.addEventField("myMODE", "MODE");
- final PlcSubscriptionRequest sub = subscription.build();
+ final PlcSubscriptionRequest sub subscription.build();
System.out.println("Query: " + sub.toString());
- final PlcSubscriptionResponse subresponse = sub.execute().get();
+ final PlcSubscriptionResponse subresponse sub.execute().get();
- if (subresponse.getResponseCode("myMODE") == PlcResponseCode.OK) { //<04>
+ if (subresponse.getResponseCode("myMODE") = PlcResponseCode.OK) { //<04>
PlcConsumerRegistration registerMode =
subresponse
.getSubscriptionHandle("myMODE") //<05>
@@ -566,7 +566,7 @@ public class PLCEventModeSubscription {
----
-==== Subscription to SYS events (S7SysEvent) and USER events (S7UserEvent).
+=== Subscription to SYS events (S7SysEvent) and USER events (S7UserEvent).
System events allow to receive asynchronously any event that affects the operation of the controller, or any of its peripheral equipment that is capable of sending events through a PROFIBUS or Profinet fieldbus.
@@ -711,17 +711,17 @@ Below is an example code for the subscription of events type *SYS*.
[source,java]
----
public static void main(String[] args) throws Exception {
- try (PlcConnection connection = new PlcDriverManager().
+ try (PlcConnection connection new PlcDriverManager().
getConnection("s7://192.168.1.51?remote-rack=0&remote-slot=3&controller-type=S7_400")) {
- final PlcSubscriptionRequest.Builder subscription = connection.subscriptionRequestBuilder(); //<01>
+ final PlcSubscriptionRequest.Builder subscription connection.subscriptionRequestBuilder(); //<01>
subscription.addEventField("mySYS", "SYS");
- final PlcSubscriptionRequest sub = subscription.build();
+ final PlcSubscriptionRequest sub subscription.build();
System.out.println("Query: " + sub.toString());
- final PlcSubscriptionResponse subresponse = sub.execute().get();
+ final PlcSubscriptionResponse subresponse sub.execute().get();
PlcConsumerRegistration registerSys =
subresponse
@@ -751,17 +751,17 @@ And below is an example code for the subscription of events type *USR*.
[source,java]
----
public static void main(String[] args) throws Exception {
- try (PlcConnection connection = new PlcDriverManager().
+ try (PlcConnection connection new PlcDriverManager().
getConnection("s7://192.168.1.51?remote-rack=0&remote-slot=3&controller-type=S7_400")) {
- final PlcSubscriptionRequest.Builder subscription = connection.subscriptionRequestBuilder();
+ final PlcSubscriptionRequest.Builder subscription connection.subscriptionRequestBuilder();
subscription.addEventField("myUSR", "USR");
- final PlcSubscriptionRequest sub = subscription.build();
+ final PlcSubscriptionRequest sub subscription.build();
System.out.println("Query: " + sub.toString());
- final PlcSubscriptionResponse subresponse = sub.execute().get();
+ final PlcSubscriptionResponse subresponse sub.execute().get();
PlcConsumerRegistration registerUsr =
subresponse
@@ -785,14 +785,14 @@ public static void main(String[] args) throws Exception {
The Java code shows how to detect the type of event in an event type *SYS*. In the S7 driver, there is an enum object _S7DiagnosticEventId_(10) that allows us to identify which internal event of the *PLC(AS)* generated it and thus, through the interpretation of the INFO1 and INFO2 fields, determine the root cause of the event.
-[NOTE, icon = s7_note.png]
+[NOTE, icon s7_note.png]
To date, the enum object _S7DiagnosticEventId_ contains a considerable amount of diagnostic values, it must be updated according to the new CPUs or firmware versions available.
Unlike *SYS* events, *USR* events must be interpreted directly by the *App* application, so they are generally scheduled during the development phase of the *S7App* application.
By having INFO1 and INFO2 in the *S7App* program, the user can transfer data associated with events, such as transitions between phases, events of diagnostic routines such as firts-out or the start or end of a batch process, all asynchronously.
-==== Subscription to ALM type events (S7AlarmEvent).
+=== Subscription to ALM type events (S7AlarmEvent).
@@ -910,7 +910,7 @@ TODO: Field description
TODO: Example code
-==== TODO: Cyclic subscription (CYC).
+=== TODO: Cyclic subscription (CYC).
The cyclical subscription allows the acquisition of data in passive mode, that is, the data is sent from the PLC in a cyclical and synchronous way.
@@ -943,7 +943,7 @@ The data transfer has three time bases:
-==== SZL System Status List
+=== SZL System Status List
The system status list gives access to the operating data of the PLC, such as memory space, operating status, status of the control switches, as well as diagnostic data of expansion cards or decentralized peripherals, PROFIBUS or PROFINET .
@@ -961,7 +961,7 @@ For a first approach to using system state lists a byte array to JSON notation p
[NOTE,icon=s7_tip.png]
Make use of the XXX document for a detailed explanation of each SZL, since as indicated, everything will depend on the hardware you have installed.
-==== Notation for SZL request
+=== Notation for SZL request
The access to the SZL of the PLC is done as a read request, where the PLCTag is formed by two fields "SZL_ID" and "INDEX".
@@ -1021,26 +1021,26 @@ public static void main(String[] args) throws Exception {
System.out.println("URL: https://cache.industry.siemens.com/dl/files/604/44240604/att_67003/v1/s7sfc_en-EN.pdf");
System.out.println("******************************************************************************************");
- try (PlcConnection connection = new DefaultPlcDriverManager().getConnection("s7://10.10.1.33?remote-rack=0&remote-slot=3&controller-type=S7_400")) { //(01)
+ try (PlcConnection connection new DefaultPlcDriverManager().getConnection("s7://10.10.1.33?remote-rack=0&remote-slot=3&controller-type=S7_400")) { //(01)
- final PlcReadRequest.Builder readrequest = connection.readRequestBuilder(); //(02)
+ final PlcReadRequest.Builder readrequest connection.readRequestBuilder(); //(02)
readrequest.addTagAddress("MySZL", "SZL_ID=16#0012;INDEX=16#0000"); //(03)
- final PlcReadRequest rr = readrequest.build(); //(04)
- final PlcReadResponse szlresponse = rr.execute().get(); //(05)
+ final PlcReadRequest rr readrequest.build(); //(04)
+ final PlcReadResponse szlresponse rr.execute().get(); //(05)
- if (szlresponse.getResponseCode("MySZL") == PlcResponseCode.OK){ //(06)
+ if (szlresponse.getResponseCode("MySZL") = PlcResponseCode.OK){ //(06)
- Collection data = szlresponse.getAllBytes("MySZL"); //(07)
- byte[] dbytes = ArrayUtils.toPrimitive(data.toArray(new Byte[data.size()])); //(08)
+ Collection data szlresponse.getAllBytes("MySZL"); //(07)
+ byte[] dbytes ArrayUtils.toPrimitive(data.toArray(new Byte[data.size()])); //(08)
- SZL szl = SZL.valueOf(0x0012); //(09)
- ByteBuf wb = wrappedBuffer(dbytes); //(10)
+ SZL szl SZL.valueOf(0x0012); //(09)
+ ByteBuf wb wrappedBuffer(dbytes); //(10)
StringBuilder sb = szl.execute(wb); //(11)
System.out.println(sb.toString()); //(12)
- } else if (szlresponse.getResponseCode("MySZL") == PlcResponseCode.NOT_FOUND){ //(13)
+ } else if (szlresponse.getResponseCode("MySZL") = PlcResponseCode.NOT_FOUND){ //(13)
System.out.println("SZL is not supported.");
}
@@ -1114,7 +1114,7 @@ From the obtained StringBuilder, you can use the JSON processor of your choice t
-==== Some useful tips
+=== Some useful tips
Especially when it comes to the input- and output addresses for analog channels, the start addresses are configurable and hereby don't always start at the same address.
In order to find out what addresses these ports have, please go to the `device setting` of your PLC in `TIA Portal`
@@ -1134,7 +1134,7 @@ The analog inputs however start at address `64`.
Each digital input and output can be addresses by a single bit-address (start-address and offset) or can be read in a block by reading a full byte starting at the given start address without providing a bit offset.
-==== Resources
+=== Resources
1. https://snap7.sourceforge.net/
2. https://support.industry.siemens.com/cs/document/13649203/simatic-net-pc-software-s7-programming-interface?dti=0&dl=en&lc=es-ES
1. https://support.industry.siemens.com/cs/document/109797648/simatic-comparison-list-for-s7-300-s7-400-s7-1200-s7-1500?dti=0&lc=en-WW
diff --git a/src/site/asciidoc/users/protocols/simulated.adoc b/src/site/asciidoc/users/protocols/simulated.adoc
index 7f299119f2d..51675f03c9c 100644
--- a/src/site/asciidoc/users/protocols/simulated.adoc
+++ b/src/site/asciidoc/users/protocols/simulated.adoc
@@ -17,9 +17,9 @@
:imagesdir: ../../images/users/protocols
:icons: font
-== Simulated
+= Simulated
-=== Connection String Options
+== Connection String Options
include::../../../plc4j/drivers/all/src/site/generated/simulated.adoc[]
@@ -39,9 +39,9 @@ include::../../../plc4j/drivers/all/src/site/generated/simulated.adoc[]
|===
-=== Individual Resource Address Format
+== Individual Resource Address Format
-==== Connection String
+=== Connection String
The simulated driver has the following connection string format:-
----
@@ -54,7 +54,7 @@ simulated://127.0.0.1
Note the transport and port fields are optional.
-==== General Format
+=== General Format
The simulated addresses have this format:
@@ -65,7 +65,7 @@ The simulated addresses have this format:
If the array-size part is omitted, the default size of `1` is assumed.
If the data-type part is omitted, it defaults to STRING.
-==== Simulation Types
+=== Simulation Types
The simulation device supports 3 different simulation types
@@ -74,13 +74,13 @@ should only be used in conjunction with a persistent connection. Once the connec
- RANDOM - This provides a new random value for each read. When writing, a log message is recorded and the value is discarded.
- STDOUT - Always returns a null value when reading. When writing, a log message is recorded and the value is discarded.
-==== Alias
+=== Alias
Aliases are used to identify the different field addresses.
They should only contain alpha-numeric and the full stop (.) character.
For readability and language specific technical purposes they should be less than 256 characters.
-==== Data Types
+=== Data Types
The following data types are supported:-
@@ -103,12 +103,12 @@ The following data types are supported:-
- WCHAR (2 byte char)
- STRING (254 bytes)
-==== Some useful tips
+=== Some useful tips
The simulation driver uses a lot of the same logic templates that is used for the other drivers. It is a good way to test PLC4X
functionality without having a device to connect to.
-==== Examples
+=== Examples
All of these address formats are valid:-
diff --git a/src/site/asciidoc/users/protocols/umas.adoc b/src/site/asciidoc/users/protocols/umas.adoc
new file mode 100644
index 00000000000..4e94f8540dc
--- /dev/null
+++ b/src/site/asciidoc/users/protocols/umas.adoc
@@ -0,0 +1,118 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+:imagesdir: ../../images/users/protocols
+:icons: font
+
+= UMAS (Schneider Electric PLCs)
+
+(Supported by Plc4Py Only)
+
+== Connection String Options
+
+[cols="2,2a,2a,2a,4a"]
+|===
+|Name |Type |Default Value |Required |Description
+|Name 4+|UMAS
+|Code 4+|`umas`
+|Default Transport 4+|`tcp`
+|Supported Transports 4+|
+ - `tcp`
+5+|Config options:
+|`request-timeout` |INT |5000| |Default timeout for all types of requests.
+|`unit-identifier` |INT |1| |Unit-identifier or slave-id that identifies the target PLC. Defaults to 1.
++++
+
+|===
+== Supported Operations
+
+[cols="2,2a,5a"]
+|===
+|Name |Value |Description
+
+3+|Supported Operations
+
+|
+2+| `read`
+
+|
+2+| `write`
+
+|
+2+| `browse`
+|===
+
+== Individual Resource Address Format
+
+=== Connection String
+
+UMAS has the following connection string format:-
+----
+umas:{transport}://{ip-address}:{port}?{options}
+----
+An example connection string would look like:-
+----
+umas:tcp://127.0.0.1:502
+----
+Note the transport, port and option fields are optional.
+
+
+=== General Format
+
+In general all UMAS addresses have this format:
+
+----
+{tag-name}.{child-name}.{child-name}:{data-type}[{array-size}]
+----
+
+Depending on the type of tag the child-name parameters are optional.
+e.g. A tag with a BOOL data type could be 'TESTING_BOOL_1' whereas
+if it is a UDT the tag name is followed by the child 'TESTING_UDT_1.START' which in itself could be a BOOL.
+
+If the array-size part is omitted, the size-default of `1` is assumed.
+
+If the data-type part is omitted, it defaults to the data type of the tag read from the PLC.
+
+=== Memory Areas
+
+Apart from tags defined in the PLC the driver is also able to access the %S and %SW
+system memory areas.
+
+The specific address details of the data in these areas are outlined in the devices
+manual.
+
+An example of the address format of these areas is %SW1 or %S20.
+
+=== Data Types
+
+The following data types are supported
+
+- BOOL (boolean)
+- SINT (int 8)
+- USINT (uint 8)
+- BYTE (uint 8)
+- INT (int 16)
+- UINT (uint 16)
+- WORD (uint 16)
+- DINT (int 32)
+- UDINT (uint 32)
+- DWORD (uint 32)
+- REAL (float)
+- STRING (char)
+- TIME
+- DATE
+- TOD (Time of Day)
+- DATE_AND_TIME
diff --git a/src/site/asciidoc/users/security.adoc b/src/site/asciidoc/users/security.adoc
index d9316052a27..a500de019d2 100644
--- a/src/site/asciidoc/users/security.adoc
+++ b/src/site/asciidoc/users/security.adoc
@@ -15,12 +15,12 @@
// limitations under the License.
//
-== Security Vulnerabilities
+= Security Vulnerabilities
Please note that binary patches are not produced for individual vulnerabilities. To obtain the binary fix for a particular vulnerability you should upgrade to an Apache PLC4X version where that vulnerability has been fixed.
For more information about reporting vulnerabilities, see the https://www.apache.org/security/[Apache Security Team] page.
-=== Known Vulnerabilities
+== Known Vulnerabilities
No vulnerabilities have been reported.
\ No newline at end of file
diff --git a/src/site/asciidoc/users/tools/capture-replay.adoc b/src/site/asciidoc/users/tools/capture-replay.adoc
index adb2ee0ed76..097536aaaff 100644
--- a/src/site/asciidoc/users/tools/capture-replay.adoc
+++ b/src/site/asciidoc/users/tools/capture-replay.adoc
@@ -15,7 +15,7 @@
// limitations under the License.
//
-== Capture Replay
+= Capture Replay
Some times the problem with industry protocols is, that the most interesting protocols live in places that are not very welcoming to IT folks.
@@ -29,7 +29,7 @@ It allows to replay recorded network traffic and to directly intercept this traf
Possibly it could also work with non passive drivers, but I expect synchronization to be tricky.
-=== Getting a Capture
+== Getting a Capture
In order to create a capture I usually connect a device running `WireShark` to the network.
@@ -39,7 +39,7 @@ An alternative would be to run `WireShark` on one of the PCs/Servers having acce
So if for example I wanted to work on a driver for control system `X`, capturing the traffic on one of the `X` servers is probably the simplest way to do it.
If complicance rules prevent ths a third option would be to use a network tap to record the capture.
-=== Replaying the Capture
+== Replaying the Capture
Now you need to copy the `pcapng` file ideally to your development system.
diff --git a/src/site/asciidoc/users/tools/connection-cache.adoc b/src/site/asciidoc/users/tools/connection-cache.adoc
index 3d92cf9e523..c717f6b5b46 100644
--- a/src/site/asciidoc/users/tools/connection-cache.adoc
+++ b/src/site/asciidoc/users/tools/connection-cache.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-=== The Connection Cache concept
+== The Connection Cache concept
In some applications there might be multiple parts of the code that require access to a PLC connection.
diff --git a/src/site/asciidoc/users/tools/connection-pool.adoc b/src/site/asciidoc/users/tools/connection-pool.adoc
index 82f43611105..f47ea49755f 100644
--- a/src/site/asciidoc/users/tools/connection-pool.adoc
+++ b/src/site/asciidoc/users/tools/connection-pool.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Connection Pool
+= Connection Pool
NOTE: The plc4j-connection-pool module has been discontinued and has been removed from PLC4X stating with version 0.11.0
@@ -41,7 +41,7 @@ Per default the PLC connection has no means of automatically re-connecting.
The `PooledPlcDriverManager` can help you with both of these scenarios.
-=== The PooledPlcDriverManager
+== The PooledPlcDriverManager
The `PooledPlcDriverManager` is a wrapper around the normal `PlcDriverManager`.
@@ -57,7 +57,7 @@ Another benefit of the `PooledPlcDriverManager` is that it will check a connecti
So if a connection was terminated, it will detect this and create a new connection.
-=== Example
+== Example
Here comes a little example program utilizing the `PooledPlcDriverManager`:
diff --git a/src/site/asciidoc/users/tools/index.adoc b/src/site/asciidoc/users/tools/index.adoc
index 4670d706076..a558327a17a 100644
--- a/src/site/asciidoc/users/tools/index.adoc
+++ b/src/site/asciidoc/users/tools/index.adoc
@@ -17,4 +17,4 @@
:imagesdir: ../../images/
:icons: font
-== Tools
+= Tools
diff --git a/src/site/asciidoc/users/tools/opm.adoc b/src/site/asciidoc/users/tools/opm.adoc
index 9192300c4f8..06a60184063 100644
--- a/src/site/asciidoc/users/tools/opm.adoc
+++ b/src/site/asciidoc/users/tools/opm.adoc
@@ -15,10 +15,10 @@
// limitations under the License.
//
-== Object PLC Mapping
+= Object PLC Mapping
-=== What is Object PLC Mapping
+== What is Object PLC Mapping
Object PLC Mapping (OPM) is heavily inspired by the Java Persistence API (JPA) [1].
One of the main goal of the PLC4X Project is to make it easy to communicate with PLC devices to enable the development
@@ -29,7 +29,7 @@ This is exactly the reason why JPA was initialized many years ago to allow the i
calling methods on POJOs (Plain old Java Object).
This is exactly what the OPM Module is for, to enable PLC communication by simply interacting with a POJO.
-=== Simple Example
+== Simple Example
The following short code snippet shows how to read one value from a PLC via OPM.
First, a _PlcEntityManager_ is instantiated, then a *connected* entity is fetched for a given PLC connection address.
@@ -64,10 +64,10 @@ public class MyEntity {
}
----
-=== Annotations
+== Annotations
-=== More details
+== More details
-=== References
+== References
[1] https://www.oracle.com/technetwork/java/javaee/tech/persistence-jsp-140049.html
\ No newline at end of file
diff --git a/src/site/asciidoc/users/tools/scraper.adoc b/src/site/asciidoc/users/tools/scraper.adoc
index 857c48f63b2..9944d669749 100644
--- a/src/site/asciidoc/users/tools/scraper.adoc
+++ b/src/site/asciidoc/users/tools/scraper.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Scraper
+= Scraper
While the Apache PLC4X API allows simple access to PLC resources, if you want to continuously monitor some values and have them retrieved in a pre-defined interval, the core PLC4X API method is a little bit uncomfortable.
@@ -29,7 +29,7 @@ As we have encountered exactly the same problem for about every integration modu
This tool automatically handles all of the tasks mentioned above.
-=== Getting started with the `Scraper`
+== Getting started with the `Scraper`
The Scraper can be found in the Maven module:
[subs=attributes+]
@@ -49,13 +49,13 @@ In general, you need 3 parts to work with the `Scraper`:
In the `Scraper` Configuration you define the so-called `jobs`.
-==== Sources
+=== Sources
Sources define connections to PLCs using PLC4X drivers.
Generally you can think of a `Source` as a PLC4X connection string, given an alias name.
-==== Jobs
+=== Jobs
A `Job` defines which resources (PLC Addresses) should be collected from which `Sources` with a given `Trigger`.
@@ -69,7 +69,7 @@ In the near future we're hoping that we will be able to support:
But, as to now, this has not been implemented yet.
-=== Configuration using the Java API
+== Configuration using the Java API
The core of the Scraper configuration is the `ScraperConfigurationTriggeredImplBuilder` class.
Use this to build the configuration objects used to bootstrap the Scraper.
@@ -138,7 +138,7 @@ As soon as we're done configuring jobs, we need to create the `Scraper` configur
ScraperConfigurationTriggeredImpl scraperConfig = builder.build();
----
-=== Running the `Scraper`
+== Running the `Scraper`
In order to run the `Scraper`, the following boilerplate code is needed.
@@ -183,7 +183,7 @@ public interface ResultHandler {
}
----
-=== Configuration using a `JSON` or `YAML` file
+== Configuration using a `JSON` or `YAML` file
As an alternative to using the Java API, the Scraper Configuration can also be read from a `JSON` or `YAML` document.
diff --git a/src/site/asciidoc/users/tools/testing.adoc b/src/site/asciidoc/users/tools/testing.adoc
index e4252c188c5..05396753086 100644
--- a/src/site/asciidoc/users/tools/testing.adoc
+++ b/src/site/asciidoc/users/tools/testing.adoc
@@ -15,9 +15,9 @@
// limitations under the License.
//
-== Testing (or using PLC4X without a PLC)
+= Testing (or using PLC4X without a PLC)
-=== The Mock Driver
+== The Mock Driver
PLC4X has a _Mock Driver_ which was initially implemented to be used for Unit Tests and this still is its main purpose.
But this driver is also very suitable to play around a bit with the PLC4X API if no _Hardware_ PLC is available.
@@ -54,7 +54,7 @@ public interface MockDevice {
}
```
-=== Simple Example
+== Simple Example
Imagine we have some Code which we cannot control or whose functionality we want to test.
This can be done with the Mock Driver in the following way.
@@ -89,7 +89,7 @@ MockDevice mockDevice = new MockDevice() {
```
This would just return a String Value `hello` for every request and print all read and write requests to the Console.
-=== Unit Testing with the Mock Driver
+== Unit Testing with the Mock Driver
To use the Mock driver in Unit Tests the easiest way is to generate the `MockDriver` instance as Mockito (or any other Framework) Mock.
Like in the following Example
@@ -149,7 +149,7 @@ verify(mockDevice).read(eq("MyAdress"));
The Snippet above shows that the part under test really has to share nothing with the test code except for the connection string.
-=== Conclusion
+== Conclusion
The above examples show that the `MockDriver` driver can not only be used to play around with the API but is also a powerful tool to
do unit testing of Code which uses the PLC4X API.
diff --git a/src/site/asciidoc/users/transports/can.adoc b/src/site/asciidoc/users/transports/can.adoc
index 6dcdda5b722..ffcbe0591e6 100644
--- a/src/site/asciidoc/users/transports/can.adoc
+++ b/src/site/asciidoc/users/transports/can.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== CAN
+= CAN
A CAN transport is a special category of transport which can bring CAN frame data to various drivers.
All of these transports are meant to follow basic CAN frame data semantics.
@@ -67,11 +67,11 @@ The CAN transport responsibility is to bring CAN data to driver implementer.
This API does not enforce, require or promote a low level bus operations.
In this regard, these operations can be made by library available for specific CAN adapter in use.
-=== Developer notes
+== Developer notes
Usage of CAN transport APIs is recommended for portability reasons.
Please have a look on link:../protocols/can.html[CAN] describe usage of CAN driver adapter with CAN transport facade.
-== Compatible CAN transports
+= Compatible CAN transports
- link:socketcan.html[SocketCAN]
\ No newline at end of file
diff --git a/src/site/asciidoc/users/transports/index.adoc b/src/site/asciidoc/users/transports/index.adoc
index 59d0f411689..cbefddf052a 100644
--- a/src/site/asciidoc/users/transports/index.adoc
+++ b/src/site/asciidoc/users/transports/index.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Transports
+= Transports
- link:tcp.html[TCP]
- link:udp.html[UDP]
diff --git a/src/site/asciidoc/users/transports/pcap-replay.adoc b/src/site/asciidoc/users/transports/pcap-replay.adoc
index 96df626959b..84163fc6b01 100644
--- a/src/site/asciidoc/users/transports/pcap-replay.adoc
+++ b/src/site/asciidoc/users/transports/pcap-replay.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== PCAP Replay
+= PCAP Replay
[cols="2,2a,5a"]
|===
diff --git a/src/site/asciidoc/users/transports/raw-socket.adoc b/src/site/asciidoc/users/transports/raw-socket.adoc
index 9ca68332f1d..53e56bb2471 100644
--- a/src/site/asciidoc/users/transports/raw-socket.adoc
+++ b/src/site/asciidoc/users/transports/raw-socket.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Raw Socket
+= Raw Socket
[cols="2,2a,5a"]
|===
diff --git a/src/site/asciidoc/users/transports/serial.adoc b/src/site/asciidoc/users/transports/serial.adoc
index 61b28867253..524c9032363 100644
--- a/src/site/asciidoc/users/transports/serial.adoc
+++ b/src/site/asciidoc/users/transports/serial.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== Serial Port
+= Serial Port
[cols="2,2a,5a"]
|===
diff --git a/src/site/asciidoc/users/transports/socketcan.adoc b/src/site/asciidoc/users/transports/socketcan.adoc
index c0c86a4a60d..0cd2c1db88a 100644
--- a/src/site/asciidoc/users/transports/socketcan.adoc
+++ b/src/site/asciidoc/users/transports/socketcan.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== SocketCAN
+= SocketCAN
[cols="2,2a,5a"]
|===
diff --git a/src/site/asciidoc/users/transports/tcp.adoc b/src/site/asciidoc/users/transports/tcp.adoc
index a5da3229e73..cf714d7bc8d 100644
--- a/src/site/asciidoc/users/transports/tcp.adoc
+++ b/src/site/asciidoc/users/transports/tcp.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== TCP
+= TCP
[cols="2,2a,5a"]
|===
diff --git a/src/site/asciidoc/users/transports/udp.adoc b/src/site/asciidoc/users/transports/udp.adoc
index 684cccd2825..fabfcd95f5c 100644
--- a/src/site/asciidoc/users/transports/udp.adoc
+++ b/src/site/asciidoc/users/transports/udp.adoc
@@ -17,7 +17,7 @@
:imagesdir: ../../images/
:icons: font
-== UDP
+= UDP
[cols="2,2a,5a"]
|===
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_1.png b/src/site/resources/images/tutorials/opcua/kse/kse_1.png
new file mode 100644
index 00000000000..7585536127d
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_1.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_10.png b/src/site/resources/images/tutorials/opcua/kse/kse_10.png
new file mode 100644
index 00000000000..1c8139524aa
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_10.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_11.png b/src/site/resources/images/tutorials/opcua/kse/kse_11.png
new file mode 100644
index 00000000000..d3293091d7e
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_11.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_12.png b/src/site/resources/images/tutorials/opcua/kse/kse_12.png
new file mode 100644
index 00000000000..57fcaf62e78
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_12.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_13.png b/src/site/resources/images/tutorials/opcua/kse/kse_13.png
new file mode 100644
index 00000000000..203d8418dfd
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_13.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_14.png b/src/site/resources/images/tutorials/opcua/kse/kse_14.png
new file mode 100644
index 00000000000..8e664ff1f48
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_14.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_15.png b/src/site/resources/images/tutorials/opcua/kse/kse_15.png
new file mode 100644
index 00000000000..bba47e167d8
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_15.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_16.png b/src/site/resources/images/tutorials/opcua/kse/kse_16.png
new file mode 100644
index 00000000000..875e67e47a8
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_16.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_17.png b/src/site/resources/images/tutorials/opcua/kse/kse_17.png
new file mode 100644
index 00000000000..e75d53c15f2
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_17.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_18.png b/src/site/resources/images/tutorials/opcua/kse/kse_18.png
new file mode 100644
index 00000000000..9161af650ee
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_18.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_2.png b/src/site/resources/images/tutorials/opcua/kse/kse_2.png
new file mode 100644
index 00000000000..9a09aeaa901
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_2.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_3.png b/src/site/resources/images/tutorials/opcua/kse/kse_3.png
new file mode 100644
index 00000000000..0c3be499ddb
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_3.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_4.png b/src/site/resources/images/tutorials/opcua/kse/kse_4.png
new file mode 100644
index 00000000000..ba5db5fa1b1
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_4.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_5.png b/src/site/resources/images/tutorials/opcua/kse/kse_5.png
new file mode 100644
index 00000000000..9ca2a411e53
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_5.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_6.png b/src/site/resources/images/tutorials/opcua/kse/kse_6.png
new file mode 100644
index 00000000000..aa1910f5d74
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_6.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_7.png b/src/site/resources/images/tutorials/opcua/kse/kse_7.png
new file mode 100644
index 00000000000..f375f3b6960
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_7.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_8.png b/src/site/resources/images/tutorials/opcua/kse/kse_8.png
new file mode 100644
index 00000000000..919c693c60c
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_8.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_9.png b/src/site/resources/images/tutorials/opcua/kse/kse_9.png
new file mode 100644
index 00000000000..d1be26bae48
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_9.png differ
diff --git a/src/site/resources/images/tutorials/opcua/kse/kse_self_signed_ca_certificate.gif b/src/site/resources/images/tutorials/opcua/kse/kse_self_signed_ca_certificate.gif
new file mode 100644
index 00000000000..84cfdfa7dce
Binary files /dev/null and b/src/site/resources/images/tutorials/opcua/kse/kse_self_signed_ca_certificate.gif differ
diff --git a/src/site/site.xml b/src/site/site.xml
index 0e4d6cd09af..4ed13d10f32 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -63,6 +63,7 @@
+
@@ -87,6 +88,7 @@
+