fix(opcuaclient): register the OpcUaClient driver factory (was always stubbed)
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Hosting;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient;
|
||||
|
||||
/// <summary>
|
||||
/// Registers the OPC UA Client driver with the <see cref="DriverFactoryRegistry"/>. The driver's
|
||||
/// <c>DriverConfig</c> JSON deserialises directly into <see cref="OpcUaClientDriverOptions"/>
|
||||
/// (the same shape <see cref="OpcUaClientDriverProbe"/> reads), so no separate DTO is needed.
|
||||
/// Mirrors <c>ModbusDriverFactoryExtensions</c> / <c>GalaxyDriverFactoryExtensions</c>.
|
||||
/// </summary>
|
||||
public static class OpcUaClientDriverFactoryExtensions
|
||||
{
|
||||
/// <summary>Driver type name — matches <c>DriverInstance.DriverType</c> values.</summary>
|
||||
public const string DriverTypeName = "OpcUaClient";
|
||||
|
||||
// Match OpcUaClientDriverProbe exactly so factory + probe parse a config identically.
|
||||
// The JsonStringEnumConverter lets enum-valued knobs (SecurityMode / SecurityPolicy /
|
||||
// AuthType / TargetNamespaceKind) be authored as their string names — the natural form
|
||||
// for human-edited + AdminUI-emitted DriverConfig JSON.
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
|
||||
/// <summary>Register the OpcUaClient factory with the driver registry.</summary>
|
||||
/// <param name="registry">The driver factory registry to register with.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory used to create per-instance loggers.</param>
|
||||
public static void Register(DriverFactoryRegistry registry, ILoggerFactory? loggerFactory = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(registry);
|
||||
registry.Register(DriverTypeName, (id, json) => CreateInstance(id, json, loggerFactory));
|
||||
}
|
||||
|
||||
/// <summary>Public for the Server-side bootstrapper + test consumers.</summary>
|
||||
/// <param name="driverInstanceId">The unique identifier for the driver instance.</param>
|
||||
/// <param name="driverConfigJson">The JSON configuration string for the driver.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory for the per-instance logger.</param>
|
||||
/// <returns>A configured <see cref="OpcUaClientDriver"/>.</returns>
|
||||
public static OpcUaClientDriver CreateInstance(
|
||||
string driverInstanceId, string driverConfigJson, ILoggerFactory? loggerFactory = null)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(driverInstanceId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(driverConfigJson);
|
||||
|
||||
var options = JsonSerializer.Deserialize<OpcUaClientDriverOptions>(driverConfigJson, JsonOptions)
|
||||
?? throw new InvalidOperationException(
|
||||
$"OpcUaClient driver config for '{driverInstanceId}' deserialised to null");
|
||||
|
||||
return new OpcUaClientDriver(options, driverInstanceId, loggerFactory?.CreateLogger<OpcUaClientDriver>());
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,14 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient;
|
||||
/// </summary>
|
||||
public sealed class OpcUaClientDriverProbe : IDriverProbe
|
||||
{
|
||||
// Kept identical to OpcUaClientDriverFactoryExtensions.JsonOptions so the probe and the
|
||||
// factory parse a given DriverConfig the same way. The JsonStringEnumConverter lets
|
||||
// enum-valued knobs be authored as their string names.
|
||||
private static readonly JsonSerializerOptions _opts = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
+1
@@ -15,6 +15,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts\ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts.csproj"/>
|
||||
<ProjectReference Include="..\..\Core\ZB.MOM.WW.OtOpcUa.Core.Abstractions\ZB.MOM.WW.OtOpcUa.Core.Abstractions.csproj"/>
|
||||
<ProjectReference Include="..\..\Core\ZB.MOM.WW.OtOpcUa.Core\ZB.MOM.WW.OtOpcUa.Core.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -102,6 +102,7 @@ public static class DriverFactoryBootstrap
|
||||
Driver.FOCAS.FocasDriverFactoryExtensions.Register(registry);
|
||||
Driver.Galaxy.GalaxyDriverFactoryExtensions.Register(registry, loggerFactory);
|
||||
Driver.Modbus.ModbusDriverFactoryExtensions.Register(registry, loggerFactory);
|
||||
Driver.OpcUaClient.OpcUaClientDriverFactoryExtensions.Register(registry, loggerFactory);
|
||||
Driver.S7.S7DriverFactoryExtensions.Register(registry);
|
||||
Driver.TwinCAT.TwinCATDriverFactoryExtensions.Register(registry);
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using Shouldly;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for <see cref="OpcUaClientDriverFactoryExtensions"/> — the factory that lets the
|
||||
/// Server-side <c>DriverFactoryBootstrap</c> materialise a real <see cref="OpcUaClientDriver"/>
|
||||
/// from a <c>DriverInstance</c> row instead of falling back to a stub.
|
||||
/// </summary>
|
||||
public class OpcUaClientDriverFactoryTests
|
||||
{
|
||||
private const string SampleConfig =
|
||||
"""{"EndpointUrl":"opc.tcp://host:4840","SecurityMode":"None","AutoAcceptCertificates":true}""";
|
||||
|
||||
/// <summary>Verifies the factory builds a driver carrying the right type + instance identity.</summary>
|
||||
[Fact]
|
||||
public void CreateInstance_builds_an_OpcUaClient_driver_with_the_right_identity()
|
||||
{
|
||||
var driver = OpcUaClientDriverFactoryExtensions.CreateInstance("drv-1", SampleConfig, NullLoggerFactory.Instance);
|
||||
driver.DriverType.ShouldBe("OpcUaClient");
|
||||
driver.DriverInstanceId.ShouldBe("drv-1");
|
||||
}
|
||||
|
||||
/// <summary>Verifies the public driver-type-name constant matches the driver's DriverType.</summary>
|
||||
[Fact]
|
||||
public void DriverTypeName_is_OpcUaClient()
|
||||
=> OpcUaClientDriverFactoryExtensions.DriverTypeName.ShouldBe("OpcUaClient");
|
||||
|
||||
/// <summary>Verifies a JSON literal that deserialises to null is rejected with a clear error.</summary>
|
||||
[Fact]
|
||||
public void CreateInstance_throws_on_null_json_deserialisation()
|
||||
=> Should.Throw<System.InvalidOperationException>(
|
||||
() => OpcUaClientDriverFactoryExtensions.CreateInstance("drv-1", "null", NullLoggerFactory.Instance));
|
||||
}
|
||||
Reference in New Issue
Block a user