Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
[wip] Increase batch and simultaneous cycle limits, update request de…
…lay, and refine error messages in tests
  • Loading branch information
PTKu committed Mar 4, 2025
commit 4dab0019c46800a8d76c128bbf969bb2eb0b1bb4
5 changes: 3 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</GlobalPackageReference>
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.2" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="System.Collections.Immutable" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="System.IO.Packaging" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
Expand All @@ -21,7 +21,8 @@
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" Condition="'$(TargetFramework)' == 'net8.0'" />

<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.2" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Web" Version="8.0.10" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageVersion Include="System.IO.Packaging" Version="8.0.0" Condition="'$(TargetFramework)' == 'net8.0'" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@


<ItemGroup>
<PackageReference Include="Microsoft.CSharp"/>
<PackageReference Include="Newtonsoft.Json"/>
<PackageReference Include="Serilog.Sinks.Console"/>
<PackageReference Include="Serilog.Sinks.File"/>
<PackageReference Include="Siemens.Simatic.S7.Webserver.API"/>
<PackageReference Include="Microsoft.CSharp" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Serilog.Sinks.Console" />
<PackageReference Include="Serilog.Sinks.File" />
<!--<PackageReference Include="Siemens.Simatic.S7.Webserver.API" />-->
</ItemGroup>

<ItemGroup>
Expand All @@ -68,6 +68,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\..\..\..\..\PTKu\simatic-s7-webserver-api\src\Webserver.API\Webserver.API.csproj" />
<ProjectReference Include="..\AXSharp.Connector\AXSharp.Connector.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ public WebApiConnector(string ipAddress, string userName, string password, bool
requestHandler = new ApiHttpClientRequestHandler(Client,
new ApiRequestFactory(ReqIdGenerator, RequestParameterChecker), ApiResponseChecker);

requestHandler.Init();

requestHandler.ApiLogout();
requestHandler.ApiLogin(UserName, UserPassword ?? string.Empty, true);

Expand Down Expand Up @@ -237,6 +239,14 @@ internal void HandleCommFailure(Exception exception, string description, IEnumer
foreach (var errorResponse in response.ErrorResponses)
{
var failedItem = originalRequest.FirstOrDefault(p => p.Id == errorResponse.Id);
if (failedItem == null)
{
var msg =
$"{errorResponse.Error.Message} [{errorResponse.Error.Code}] : {string.Join(";", originalRequest.Select(p => $"Id:{p.Id}| Method : {p.Method}, {string.Join("; ", p.Params.Select(p => $"{p.Key} : {p.Value}"))}"))}";
Logger.Error(msg);
continue;
}

var failedItemParams = string.Join(";", failedItem.Params.Select(p => $"{p.Key} : {p.Value}"));
if (string.IsNullOrEmpty(firstFailedItemParams))
{
Expand Down Expand Up @@ -351,10 +361,11 @@ public override async Task ReadBatchAsync(IEnumerable<ITwinPrimitive>? primitive

var webApiPrimitives = twinPrimitives.Cast<IWebApiPrimitive>().Distinct().ToArray();

foreach (var requestSegment in webApiPrimitives.SegmentReadRequest(MAX_READ_REQUEST_SEGMENT))
//foreach (var requestSegment in webApiPrimitives.SegmentReadRequest(MAX_READ_REQUEST_SEGMENT))
{
var requestSegment = webApiPrimitives;
var apiPrimitives = requestSegment as IWebApiPrimitive[] ?? requestSegment.ToArray();
var segment = apiPrimitives.Select(p => p.PeekPlcReadRequestData).ToList();
var segment = apiPrimitives.Select(p => p.PlcReadRequestData).ToList();
try
{
await RetryPolicy.ExecuteAsync(async () => responseData = await RequestHandler.ApiBulkAsync(segment));
Expand Down Expand Up @@ -408,7 +419,7 @@ public override async Task ReadBatchAsync(IEnumerable<ITwinPrimitive>? primitive
/// <inheritdoc />
public override async Task WriteBatchAsync(IEnumerable<ITwinPrimitive>? primitives)
{
if (primitives == null) return;
if (primitives == null || !primitives.Any()) return;

try
{
Expand All @@ -425,12 +436,13 @@ public override async Task WriteBatchAsync(IEnumerable<ITwinPrimitive>? primitiv

var webApiPrimitives = twinPrimitives.Cast<IWebApiPrimitive>().Distinct().ToArray();

foreach (var requestSegment in webApiPrimitives.SegmentWriteRequest(MAX_WRITE_REQUEST_SEGMENT))
//foreach (var requestSegment in webApiPrimitives.SegmentWriteRequest(MAX_WRITE_REQUEST_SEGMENT))
{
var requestSegment = webApiPrimitives;
var apiPrimitives = requestSegment as IWebApiPrimitive[] ?? requestSegment.ToArray();
try
{
await RetryPolicy.ExecuteAsync(async () => await RequestHandler.ApiBulkAsync(apiPrimitives.Select(p => p.PeekPlcWriteRequestData)));
await RetryPolicy.ExecuteAsync(async () => await RequestHandler.ApiBulkAsync(apiPrimitives.Select(p => p.PlcWriteRequestData)));
}
catch (ApiBulkRequestException apiException)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1779,7 +1779,7 @@ public async Task should_report_failure_when_unable_to_read_single_item()

Assert.Equal(true, myBYTE.AccessStatus.Failure);
output.WriteLine(myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch read failed.: 'During Bulk request for 1 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse' [var : \"TGlobalVariablesDB\".myBYTE_does_not_exist] ", myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch read failed.: 'During Bulk request for 1 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse, errors:{\"Code\":200,\"Message\":\"Address does not exist\"}\r\n' [var : \"TGlobalVariablesDB\".myBYTE_does_not_exist] ", myBYTE.AccessStatus.FailureReason);
}

[Fact]
Expand All @@ -1792,7 +1792,7 @@ public async Task should_report_failure_when_unable_to_write_single_item()

Assert.Equal(true, myBYTE.AccessStatus.Failure);
output.WriteLine(myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch write failed.: 'During Bulk request for 1 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse' [var : \"TGlobalVariablesDB\".myBYTE_does_not_exist;value : 55] ", myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch write failed.: 'During Bulk request for 1 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse, errors:{\"Code\":200,\"Message\":\"Address does not exist\"}\r\n' [var : \"TGlobalVariablesDB\".myBYTE_does_not_exist;value : 55] ", myBYTE.AccessStatus.FailureReason);
}


Expand All @@ -1817,7 +1817,7 @@ public async Task should_report_failure_when_unable_to_bulk_read_items()

Assert.Equal(true, myBYTE.AccessStatus.Failure);
output.WriteLine(myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch read failed.: 'During Bulk request for 3 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse' [var : \"TGlobalVariablesDB\".myBYTE_o] ", myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch read failed.: 'During Bulk request for 3 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse, errors:{\"Code\":200,\"Message\":\"Address does not exist\"}\r\n' [var : \"TGlobalVariablesDB\".myBYTE_o] ", myBYTE.AccessStatus.FailureReason);
}

[Fact]
Expand All @@ -1840,7 +1840,7 @@ public async Task should_report_failure_when_unable_to_bulk_write_items()

Assert.Equal(true, myBYTE.AccessStatus.Failure);
output.WriteLine(myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch write failed.: 'During Bulk request for 3 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse' [var : \"TGlobalVariablesDB\".myBYTE_o;value : 0] ", myBYTE.AccessStatus.FailureReason);
Assert.Equal("Batch write failed.: 'During Bulk request for 3 there have been 1 Errors:\r\nFor details: Check the Property BulkResponse, errors:{\"Code\":200,\"Message\":\"Address does not exist\"}\r\n' [var : \"TGlobalVariablesDB\".myBYTE_o;value : 0] ", myBYTE.AccessStatus.FailureReason);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ namespace AXSharp.Connector.S71500.WebApi.Tests.Issues;
public class GH_PTKu_ix_xx : IDisposable
{
private readonly ITestOutputHelper report;
private readonly int batchCycles = 3;
private readonly int batchCycles = 10;

private readonly int simultaneousCycles = 10;
private readonly int simultaneousCycles = 20;

public GH_PTKu_ix_xx(ITestOutputHelper output)
{
Expand All @@ -32,7 +32,7 @@ public GH_PTKu_ix_xx(ITestOutputHelper output)
Task.Delay(1000).Wait();
report = output;
Plc.Connector.ConcurrentRequestMaxCount = 3;
Plc.Connector.ConcurrentRequestDelay = 3;
Plc.Connector.ConcurrentRequestDelay = 10;
report.WriteLine($"Max requests limit: {Plc.Connector.ConcurrentRequestMaxCount}");
report.WriteLine($"Concurrent request delay: {Plc.Connector.ConcurrentRequestDelay}");
}
Expand Down
14 changes: 14 additions & 0 deletions src/AXSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AXSharp.TIA2AX.Transformer"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AXSharp.TIA2AX.TransformerTests", "AXSharp.tools\src\AXSharp.TIA2AX.TranformerTests\AXSharp.TIA2AX.TransformerTests.csproj", "{ECC1D9CE-EB81-430D-9784-007700D285FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Webserver.API", "..\..\..\..\PTKu\simatic-s7-webserver-api\src\Webserver.API\Webserver.API.csproj", "{F0E56D9A-A83F-4761-AE65-D433C877C30F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -630,6 +632,18 @@ Global
{ECC1D9CE-EB81-430D-9784-007700D285FE}.Release|x64.Build.0 = Release|Any CPU
{ECC1D9CE-EB81-430D-9784-007700D285FE}.Release|x86.ActiveCfg = Release|Any CPU
{ECC1D9CE-EB81-430D-9784-007700D285FE}.Release|x86.Build.0 = Release|Any CPU
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Debug|x64.ActiveCfg = Debug|x64
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Debug|x64.Build.0 = Debug|x64
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Debug|x86.ActiveCfg = Debug|x86
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Debug|x86.Build.0 = Debug|x86
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Release|Any CPU.Build.0 = Release|Any CPU
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Release|x64.ActiveCfg = Release|x64
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Release|x64.Build.0 = Release|x64
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Release|x86.ActiveCfg = Release|x86
{F0E56D9A-A83F-4761-AE65-D433C877C30F}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down