Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature/modbus optimizer #1744

Merged
merged 10 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASE_NOTES
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ New Features
them back together. It is now possible to read arrays of
almost unlimited size.
- Added auto-discovery to the EIP and KNXNet/IP Drivers.
- Added an Optimizer to the Modbus driver, that improves read
performance of multi-item read requests by more than 10 times.

Incompatible changes
--------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@

int8_t plc4c_test_read_write_crc_int8();
uint8_t plc4c_test_read_write_crc_uint8();
uint8_t plc4c_test_read_write_read_manual_field(plc4c_spi_read_buffer* readBuffer, uint8_t value);
plc4c_return_code plc4c_test_read_write_write_manual_field(plc4c_spi_write_buffer* writeBuffer, uint8_t value);
uint8_t plc4c_test_read_write_read_a_manual_field(plc4c_spi_read_buffer* readBuffer, uint8_t value);
plc4c_return_code plc4c_test_read_write_write_a_manual_field(plc4c_spi_write_buffer* writeBuffer, uint8_t value);

#ifdef __cplusplus
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,11 @@ namespace org.apache.plc4net.drivers.${protocolName?replace("-", "")}.${outputFl
<#if arrayField.loopExpression.contains("curPos")>
curPos = readBuffer.getPos() - startPos;
</#if>
<#if elementTypeReference.isByteBased()>
var ${arrayField.name} = readBuffer.ReadByteArray("", ${helper.toParseExpression(arrayField, helper.intTypeReference, arrayField.loopExpression, parserArguments)});
<#else>
<#-- If this is a count array, we can directly initialize an array with the given size -->
<#if field.isCountArrayField()>
<#if field.isCountArrayField()>
// Count array
List<IPlcValue> ${arrayField.name};
{
Expand All @@ -111,40 +114,41 @@ namespace org.apache.plc4net.drivers.${protocolName?replace("-", "")}.${outputFl
}
}
<#-- In all other cases do we have to work with a list, that is later converted to an array -->
<#else>
<#else>
<#-- For a length array, we read data till the read position of the buffer reaches a given position -->
<#if arrayField.isLengthArrayField()>
<#if arrayField.isLengthArrayField()>
// Length array
var _${arrayField.name}Length = ${helper.toParseExpression(arrayField, helper.intTypeReference, arrayField.loopExpression,parserArguments)};
var ${arrayField.name}EndPos = readBuffer.getPos() + _${arrayField.name}Length;
var value = new List<IPlcValue>();
while(readBuffer.getPos() < ${arrayField.name}EndPos) {
value.Add(
<#if elementTypeReference.isSimpleTypeReference()>
<#if elementTypeReference.isSimpleTypeReference()>
new ${helper.getPlcValueTypeForTypeReference(elementTypeReference)}(${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)})
<#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer
<#if elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.isPresent()>,
<#list elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>
<#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer
<#if elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.isPresent()>,
<#list elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>
(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index))}) (${helper.toParseExpression(arrayField,elementTypeReference, parserArgument,parserArguments)})
<#sep>, </#sep>
</#list>
</#if>
<#sep>, </#sep>
</#list>
</#if>
)
</#if>
</#if>
);
}
<#-- A terminated array keeps on reading data as long as the termination expression evaluates to false -->
<#elseif arrayField.isTerminatedArrayField()>
<#elseif arrayField.isTerminatedArrayField()>
// Terminated array
var ${arrayField.name} = new List<${helper.getLanguageTypeNameForField(arrayField)}>();
while(!((boolean) (${helper.toParseExpression(arrayField, helper.boolTypeReference, arrayField.loopExpression,parserArguments)}))) {
${arrayField.name}.Add(<#if elementTypeReference.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "", arrayField)}<#else>${elementTypeReference.asNonSimpleTypeReference().orElseThrow().name}IO.StaticParse(readBuffer<#if elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.isPresent()>, <#list elementTypeReference.asNonSimpleTypeReference().orElseThrow().params.orElseThrow() as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(elementTypeReference, parserArgument?index))}) (${helper.toParseExpression(arrayField, elementTypeReference, parserArgument, parserArguments)})<#sep>, </#sep></#list></#if>)</#if>);

<#-- After parsing, update the current position, but only if it's needed -->
<#if arrayField.loopExpression.contains("curPos")>
<#if arrayField.loopExpression.contains("curPos")>
curPos = readBuffer.getPos() - startPos;
</#if>
</#if>
}
</#if>
</#if>
</#if>
<#if arrayField.name == "value">
Expand Down Expand Up @@ -218,8 +222,10 @@ namespace org.apache.plc4net.drivers.${protocolName?replace("-", "")}.${outputFl
<#-- In this case we need to wrap each field in a IPlcValue that matches it's natural type -->
var _map = new Dictionary<string, IPlcValue>();
<#list case.fields as field>
<#if field.isArrayField()>
<#if field.isArrayField() && field.asArrayField().orElseThrow().type.elementTypeReference.isByteBased()>
<#assign field=field.asArrayField().orElseThrow()>
_map["${field.name}"] = new PlcRawByteArray(${field.name});
<#elseif field.isArrayField()>
_map["${field.name}"] = new PlcList(${field.name});
<#elseif field.isPropertyField()>
<#assign field=field.asPropertyField().orElseThrow()>
Expand Down Expand Up @@ -321,7 +327,7 @@ namespace org.apache.plc4net.drivers.${protocolName?replace("-", "")}.${outputFl
return new Plc${case.name}(value);
</#switch>
</#if>
}<#sep> else </#sep></#list>
} </#list>
<#if !defaultCaseOutput>
return null;
</#if>
Expand Down Expand Up @@ -422,7 +428,7 @@ namespace org.apache.plc4net.drivers.${protocolName?replace("-", "")}.${outputFl
</#switch>
</#list>
return writeBuffer;
}<#sep> else </#sep></#list>
} </#list>
<#if !defaultCaseOutput>
return null;
</#if>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ func ${type.name}ParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffe
<#assign arrayElementType = arrayField.type.elementTypeReference>

// Array Field (${arrayField.name})
<#if arrayElementType.isByteBased()>
<#if !field.isCountArrayField() && !field.isLengthArrayField()>
return nil, errors.Wrap(_${arrayField.name}Err, "Array fields of type byte only support 'count' and 'length' loop-types.")<@emitImport import="github.com/pkg/errors" />
</#if>
${arrayField.name}, _${arrayField.name}Err := readBuffer.ReadByteArray("${arrayField.name}", int(${helper.toParseExpression(null, null, arrayField.loopExpression, parserArguments)}))<#if arrayField.loopExpression.contains("CEIL")><@emitImport import="math" /></#if>
if _${arrayField.name}Err != nil {
return nil, errors.Wrap(_${arrayField.name}Err, "Error parsing '${arrayField.name}' field")<@emitImport import="github.com/pkg/errors" />
}
<#else>
var ${arrayField.name} []api.PlcValue
for i := 0; i < int(${helper.toParseExpression(null, null, arrayField.loopExpression, parserArguments)}); i++ {
_item, _itemErr := <#if arrayElementType.isSimpleTypeReference()>${helper.getReadBufferReadMethodCall(arrayField.name, arrayElementType.asSimpleTypeReference().orElseThrow(), arrayField)}<#else>Complex type array in data-io parsing currently not implemented</#if>
Expand All @@ -128,6 +137,7 @@ func ${type.name}ParseWithBuffer(ctx context.Context, readBuffer utils.ReadBuffe
}
${arrayField.name} = append(${arrayField.name}, ${helper.getPlcValueTypeForTypeReference(arrayElementType)}(_item))
}
</#if>
<#if arrayField.name == "value">
<#assign valueDefined=true>
</#if>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ${type.name}:
<#if discriminatorType.isEnumTypeReference()>
${helper.getLanguageTypeNameForTypeReference(discriminatorType)}.${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments)}
<#else>
${helper.camelCaseToSnakeCase(helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments))}
${helper.toParseExpression(dataIoTypeDefinition.switchField.orElseThrow(), discriminatorType, discriminatorValueTerm, parserArguments)}
</#if>
<#sep> and </#sep>
</#list>
Expand Down Expand Up @@ -131,7 +131,7 @@ class ${type.name}:
)
</@compress>

<#-- A terminated array keeps on reading data as long as the termination expression evaluates to false -->
<#-- A terminated array keeps on reading data as long as the termination expression evaluates to False -->
<#elseif arrayField.isTerminatedArrayField()>
# Terminated array
${arrayField.name}: ${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)} = new LinkedList<>()
Expand Down Expand Up @@ -377,8 +377,8 @@ class ${type.name}:
for val in values.get_list():
<#if elementTypeReference.isByteBased()>
<@emitImport import="from typing import List" />
value: list[byte] = val.get_raw()
write_buffer.write_byte_array("", value)
value: ${helper.getLanguageTypeNameForField(arrayField)} = val.get_raw()
write_buffer.write_byte_array("", value)
<#else>
value: ${helper.getLanguageTypeNameForTypeReference(elementTypeReference)} = val.get_${helper.camelCaseToSnakeCase(helper.getLanguageTypeNameForTypeReference(elementTypeReference)?cap_first)}()
${helper.getWriteBufferWriteMethodCall(elementTypeReference.asSimpleTypeReference().orElseThrow(), "(" + arrayField.name + ")", arrayField)}
Expand All @@ -387,7 +387,7 @@ class ${type.name}:

<#if case.name == "BOOL">
while write_buffer.getPos() < len(write_buffer.get_data()):
write_buffer.write_bit(false)
write_buffer.write_bit(False)
</#if>
<#break>
<#case "const">
Expand Down
Loading
Loading