Skip to content

Commit

Permalink
add recursive browse with bulk requests for arrays (#106)
Browse files Browse the repository at this point in the history
* add recursive browse with bulk requests for arrays

* async non async

* no cancellation token
  • Loading branch information
KircMax authored Feb 26, 2025
1 parent 6eef5d2 commit 530c9b2
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/Webserver.API/Services/PlcProgram/ApiPlcProgramHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: MIT
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Siemens.Simatic.S7.Webserver.API.Enums;
using Siemens.Simatic.S7.Webserver.API.Models;
using Siemens.Simatic.S7.Webserver.API.Models.Requests;
Expand Down Expand Up @@ -199,5 +200,88 @@ public ApiPlcProgramData PlcProgramReadStructByChildValues(ApiPlcProgramData str
/// <returns>The Struct containing the Children with their according Values</returns>
public ApiBulkResponse PlcProgramWriteStructByChildValues(ApiPlcProgramData structToWrite, ApiPlcDataRepresentation childrenWriteMode = ApiPlcDataRepresentation.Simple)
=> PlcProgramWriteStructByChildValuesAsync(structToWrite, childrenWriteMode).GetAwaiter().GetResult();

/// <summary>
/// Recursively Browse through everything 'underneath' the given block / Structure / block element
/// </summary>
/// <param name="rootNodeForRecursiveBrowse">The </param>
/// <param name="cancellationToken">Cancellation token for the operation</param>
public async Task RecursivePlcProgramBrowseAsync(ApiPlcProgramData rootNodeForRecursiveBrowse, CancellationToken cancellationToken = default(CancellationToken))
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
if (rootNodeForRecursiveBrowse.Has_children ?? false)
{
var items = (PlcProgramBrowseSetChildrenAndParents(ApiPlcProgramBrowseMode.Children, rootNodeForRecursiveBrowse)).Result;
foreach (var item in items)
{
switch (item.Datatype)
{
case ApiPlcProgramDataType.Struct:
case ApiPlcProgramDataType.DataBlock:
if (item.ArrayElements.Any())
{
var requests = new List<IApiRequest>();
foreach (var element in item.ArrayElements)
{
var varNameForMethods = element.GetVarNameForMethods();
var requestToAdd = _requestFactory.GetApiPlcProgramBrowseRequest(ApiPlcProgramBrowseMode.Children, varNameForMethods);
_logger?.LogTrace($"Add PlcProgram Browse request for '{varNameForMethods}' -> mode '{ApiPlcProgramBrowseMode.Children}'");
requests.Add(requestToAdd);
}
requests = _requestFactory.GetApiBulkRequestWithUniqueIds(requests).ToList();
if (requests.Count > 0)
{
var childvalues = await _apiRequestHandler.ApiBulkAsync(requests, cancellationToken);
foreach (var childval in childvalues.SuccessfulResponses) // as IEnumerable<ApiPlcProgramBrowseResponse>
{
var accordingObjects = (childval.Result as JArray).ToObject<List<ApiPlcProgramData>>();
accordingObjects.ForEach(el =>
{
el.Parents = new List<ApiPlcProgramData>(item.Parents);
el.Parents.Add(item);
_logger?.LogTrace($"add parent '{item.Name}' to '{el.Name}'");
if (item.Children == null)
{
item.Children = new List<ApiPlcProgramData>();
}
if (el.ArrayElements?.Count != 0)
{
foreach (var arrayEl in el.ArrayElements)
{
arrayEl.Parents = el.Parents;
_logger?.LogTrace($"add parent '{el.Name}' to '{arrayEl.Name}'");
}
}
if (!item.Children.Any(child => child.Equals(el)))
{
item.Children.Add(el);
_logger?.LogTrace($"add child '{el.Name}' to '{item.Name}'");
}
});
}
}
}
else
{
await RecursivePlcProgramBrowseAsync(item);
}
break;
default:
// end element, no need to 'further browse'
break;
}
}
}
}

/// <summary>
/// Recursively Browse through everything 'underneath' the given block / Structure / block element
/// </summary>
/// <param name="rootNodeForRecursiveBrowse">The </param>
public void RecursivePlcProgramBrowse(ApiPlcProgramData rootNodeForRecursiveBrowse)
=> RecursivePlcProgramBrowseAsync(rootNodeForRecursiveBrowse).GetAwaiter().GetResult();
}
}
12 changes: 12 additions & 0 deletions src/Webserver.API/Services/PlcProgram/IApiPlcProgramHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,17 @@ public interface IApiPlcProgramHandler
/// <param name="cancellationToken">Enables the method to terminate its operation if a cancellation is requested from it's CancellationTokenSource.</param>
/// <returns>The Struct containing the Children with their according Values</returns>
Task<ApiBulkResponse> PlcProgramWriteStructByChildValuesAsync(ApiPlcProgramData structToWrite, ApiPlcDataRepresentation childrenWriteMode = ApiPlcDataRepresentation.Simple, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Recursively Browse through everything 'underneath' the given block / Structure / block element
/// </summary>
/// <param name="rootNodeForRecursiveBrowse">The </param>
/// <param name="cancellationToken">Cancellation token for the operation</param>
Task RecursivePlcProgramBrowseAsync(ApiPlcProgramData rootNodeForRecursiveBrowse, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Recursively Browse through everything 'underneath' the given block / Structure / block element
/// </summary>
/// <param name="rootNodeForRecursiveBrowse">The </param>
void RecursivePlcProgramBrowse(ApiPlcProgramData rootNodeForRecursiveBrowse);
}
}

0 comments on commit 530c9b2

Please sign in to comment.