Files
Copilot 5dd53ff9d0 [Server] Migrate all NodeManagers to AsyncCustomNodeManager (#3817)
Migrate all NodeManagers to IAsyncNodeManager
Add more Tests

## Related Issues

Issue linking is handled automatically by the system.

## Types of changes

What types of changes does your code introduce?  
_Put an `x` in the boxes that apply. You can also fill these out after
creating the PR._

- [x] Bugfix (non-breaking change which fixes an issue)
- [ ] Enhancement (non-breaking change which adds functionality)
- [ ] Test enhancement (non-breaking change to increase test coverage)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected, requires version increase of
Nuget packages)
- [ ] Documentation Update (if none of the other choices apply)

## Checklist

_Put an `x` in the boxes that apply. You can also fill these out after
creating the PR. If you're unsure about any of them, don't hesitate to
ask. We're here to help! This is simply a reminder of what we are going
to look for before merging your code._

- [ ] I have read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf).
- [x] I ran tests locally with my changes, all passed.
- [x] I fixed all failing tests in the CI pipelines. 
- [x] I fixed all introduced issues with CodeQL and LGTM.
- [ ] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [ ] I have added necessary documentation (if appropriate).
- [ ] Any dependent changes have been merged and published in downstream
modules.

## Further comments

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <romanett98@gmail.com>
Co-authored-by: Marc Schier <marcschier@users.noreply.github.com>
2026-05-28 20:24:22 +02:00

184 lines
7.1 KiB
C#

/* ========================================================================
* Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Opc.Ua;
using Opc.Ua.Server;
namespace Quickstarts.Servers
{
/// <summary>
/// Helpers to find node managers implemented in this library.
/// </summary>
public static class Utils
{
/// <summary>
/// Applies custom settings to quickstart servers for CTT run.
/// </summary>
public static async Task ApplyCTTModeAsync(TextWriter output, IStandardServer server)
{
var methodsToCall = new List<CallMethodRequest>();
int index = server.CurrentInstance.NamespaceUris.GetIndex(Alarms.Namespaces.Alarms);
if (index > 0)
{
try
{
methodsToCall.Add(
// Start the Alarms with infinite runtime
new CallMethodRequest
{
MethodId = new NodeId("Alarms.Start", (ushort)index),
ObjectId = new NodeId("Alarms", (ushort)index),
InputArguments = [new Variant(uint.MaxValue)]
});
var requestHeader = new RequestHeader
{
Timestamp = DateTime.UtcNow,
TimeoutHint = 10000
};
var context = new OperationContext(requestHeader, null, RequestType.Call, RequestLifetime.None);
(ArrayOf<CallMethodResult> results, ArrayOf<DiagnosticInfo> diagnosticInfos) = await server.CurrentInstance.NodeManager.CallAsync(
context,
methodsToCall)
.ConfigureAwait(false);
foreach (CallMethodResult result in results)
{
if (ServiceResult.IsBad(result.StatusCode))
{
ILogger<StandardServer> logger =
server.CurrentInstance.Telemetry.CreateLogger<StandardServer>();
logger.LogError("Error calling method with status code {StatusCode}.", result.StatusCode);
}
}
output.WriteLine("The Alarms for CTT mode are active.");
return;
}
catch (Exception ex)
{
ILogger<StandardServer> logger = server.CurrentInstance.Telemetry.CreateLogger<StandardServer>();
logger.LogError(ex, "Failed to start alarms for CTT.");
}
}
output.WriteLine(
"The alarms could not be enabled for CTT, the namespace does not exist.");
}
/// <summary>
/// Add all available node manager factories to the server.
/// </summary>
public static void AddDefaultNodeManagers(IStandardServer server)
{
foreach (INodeManagerFactory nodeManagerFactory in NodeManagerFactories)
{
server.AddNodeManager(nodeManagerFactory);
}
foreach (IAsyncNodeManagerFactory asyncFactory in AsyncNodeManagerFactories)
{
server.AddNodeManager(asyncFactory);
}
}
/// <summary>
/// Add all available node manager factories to the server.
/// </summary>
public static void UseSamplingGroupsInReferenceNodeManager(
ReferenceServer.ReferenceServer server)
{
server.UseSamplingGroupsInReferenceNodeManager = true;
}
/// <summary>
/// Enable provisioning mode in the ReferenceServer.
/// </summary>
public static void EnableProvisioningMode(
ReferenceServer.ReferenceServer server)
{
server.ProvisioningMode = true;
}
/// <summary>
/// The property with available node manager factories.
/// </summary>
public static ArrayOf<INodeManagerFactory> NodeManagerFactories
{
get
{
s_nodeManagerFactories ??= GetNodeManagerFactories();
return s_nodeManagerFactories.ToArrayOf();
}
}
/// <summary>
/// The property with available async node manager factories.
/// </summary>
public static ArrayOf<IAsyncNodeManagerFactory> AsyncNodeManagerFactories
{
get
{
s_asyncNodeManagerFactories ??= GetAsyncNodeManagerFactories();
return s_asyncNodeManagerFactories.ToArrayOf();
}
}
/// <summary>
/// Enumerates all node manager factories.
/// </summary>
private static List<INodeManagerFactory> GetNodeManagerFactories()
{
List<INodeManagerFactory> nodeManagerFactories = [];
nodeManagerFactories.Add(new MemoryBuffer.MemoryBufferNodeManagerFactory());
nodeManagerFactories.Add(new Boiler.BoilerNodeManagerFactory());
return nodeManagerFactories;
}
/// <summary>
/// Enumerates all async node manager factories.
/// </summary>
private static List<IAsyncNodeManagerFactory> GetAsyncNodeManagerFactories()
{
List<IAsyncNodeManagerFactory> factories = [];
factories.Add(new TestData.TestDataNodeManagerFactory());
factories.Add(new Alarms.AlarmNodeManagerFactory());
return factories;
}
private static IList<INodeManagerFactory>? s_nodeManagerFactories;
private static IList<IAsyncNodeManagerFactory>? s_asyncNodeManagerFactories;
}
}