feat(adminui): Transport dropdown on AbCip/AbLegacy driver forms (live-verified on docker-dev)
- AbCip/AbLegacy driver forms gain a Transport InputSelect; FromOptions/ToOptions now carry Transport, so saving any other field no longer silently reverts Native to libplctag. - Both drivers log the constructed transport once per init. - AbCip factory now takes the host ILoggerFactory (it ran on NullLogger in production, hiding every AbCip log line); DriverFactoryBootstrap passes it. - Gate results: AdminUI /run (T19) native, inverted (dead port) and libplctag legs.
This commit is contained in:
+17
-2
@@ -32,6 +32,14 @@
|
||||
</div>
|
||||
<div class="form-text">Only enable when UDT member declaration order matches controller compiled layout.</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" for="abcipTransport">Transport</label>
|
||||
<InputSelect @bind-Value="_form.Transport" @bind-Value:after="EmitAsync" class="form-select form-select-sm" id="abcipTransport">
|
||||
<option value="@AbCipTransport.Libplctag">libplctag (default)</option>
|
||||
<option value="@AbCipTransport.Native">Native (managed)</option>
|
||||
</InputSelect>
|
||||
<div class="form-text">Which protocol stack talks to the controller. Takes effect on the next deploy.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -136,7 +144,11 @@
|
||||
/// Devices array forward (the device form authors the real endpoints; the merge reconstructs the array
|
||||
/// from the device rows at deploy/probe time).</summary>
|
||||
public string GetConfigJson()
|
||||
=> JsonSerializer.Serialize(_form.ToOptions(_preservedDevices), _jsonOpts);
|
||||
=> Serialize(_form.ToOptions(_preservedDevices));
|
||||
|
||||
/// <summary>Serializes options with the form's JSON settings (camelCase, enums as strings).</summary>
|
||||
internal static string Serialize(AbCipDriverOptions options)
|
||||
=> JsonSerializer.Serialize(options, _jsonOpts);
|
||||
|
||||
private async Task EmitAsync()
|
||||
{
|
||||
@@ -151,7 +163,7 @@
|
||||
await ResilienceConfigChanged.InvokeAsync(r);
|
||||
}
|
||||
|
||||
private static AbCipDriverOptions? TryDeserialize(string json)
|
||||
internal static AbCipDriverOptions? TryDeserialize(string json)
|
||||
{
|
||||
try { return JsonSerializer.Deserialize<AbCipDriverOptions>(json, _jsonOpts); }
|
||||
catch { return null; }
|
||||
@@ -163,6 +175,7 @@
|
||||
{
|
||||
// Operation
|
||||
public int TimeoutSeconds { get; set; } = 2;
|
||||
public AbCipTransport Transport { get; set; } = AbCipTransport.Libplctag;
|
||||
public bool EnableControllerBrowse { get; set; } = false;
|
||||
public bool EnableDeclarationOnlyUdtGrouping { get; set; } = false;
|
||||
|
||||
@@ -182,6 +195,7 @@
|
||||
public static FormModel FromOptions(AbCipDriverOptions o) => new()
|
||||
{
|
||||
TimeoutSeconds = (int)o.Timeout.TotalSeconds,
|
||||
Transport = o.Transport,
|
||||
EnableControllerBrowse = o.EnableControllerBrowse,
|
||||
EnableDeclarationOnlyUdtGrouping = o.EnableDeclarationOnlyUdtGrouping,
|
||||
EnableAlarmProjection = o.EnableAlarmProjection,
|
||||
@@ -205,6 +219,7 @@
|
||||
ProbeTagPath = string.IsNullOrWhiteSpace(ProbeTagPath) ? null : ProbeTagPath,
|
||||
},
|
||||
Timeout = TimeSpan.FromSeconds(TimeoutSeconds),
|
||||
Transport = Transport,
|
||||
EnableControllerBrowse = EnableControllerBrowse,
|
||||
EnableAlarmProjection = EnableAlarmProjection,
|
||||
AlarmPollInterval = TimeSpan.FromSeconds(AlarmPollIntervalSeconds),
|
||||
|
||||
+17
-2
@@ -19,6 +19,14 @@
|
||||
<InputNumber @bind-Value="_form.TimeoutSeconds" @bind-Value:after="EmitAsync" class="form-control form-control-sm" />
|
||||
<div class="form-text">Default read/write timeout. Default 2 s.</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label" for="ablegacyTransport">Transport</label>
|
||||
<InputSelect @bind-Value="_form.Transport" @bind-Value:after="EmitAsync" class="form-select form-select-sm" id="ablegacyTransport">
|
||||
<option value="@AbLegacyTransport.Libplctag">libplctag (default)</option>
|
||||
<option value="@AbLegacyTransport.Native">Native (managed)</option>
|
||||
</InputSelect>
|
||||
<div class="form-text">Which protocol stack talks to the controller. Takes effect on the next deploy.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -101,7 +109,11 @@
|
||||
/// <summary>Serializes the current channel/protocol config to camelCase JSON, preserving the driver's
|
||||
/// existing Devices array (authored as separate v3 entities).</summary>
|
||||
public string GetConfigJson()
|
||||
=> JsonSerializer.Serialize(_form.ToOptions(_preservedDevices), _jsonOpts);
|
||||
=> Serialize(_form.ToOptions(_preservedDevices));
|
||||
|
||||
/// <summary>Serializes options with the form's JSON settings (camelCase, enums as strings).</summary>
|
||||
internal static string Serialize(AbLegacyDriverOptions options)
|
||||
=> JsonSerializer.Serialize(options, _jsonOpts);
|
||||
|
||||
private async Task EmitAsync()
|
||||
{
|
||||
@@ -116,7 +128,7 @@
|
||||
await ResilienceConfigChanged.InvokeAsync(r);
|
||||
}
|
||||
|
||||
private static AbLegacyDriverOptions? TryDeserialize(string json)
|
||||
internal static AbLegacyDriverOptions? TryDeserialize(string json)
|
||||
{
|
||||
try { return JsonSerializer.Deserialize<AbLegacyDriverOptions>(json, _jsonOpts); }
|
||||
catch { return null; }
|
||||
@@ -128,6 +140,7 @@
|
||||
{
|
||||
// Operation
|
||||
public int TimeoutSeconds { get; set; } = 2;
|
||||
public AbLegacyTransport Transport { get; set; } = AbLegacyTransport.Libplctag;
|
||||
|
||||
// Probe
|
||||
public bool ProbeEnabled { get; set; } = true;
|
||||
@@ -145,6 +158,7 @@
|
||||
public static FormModel FromOptions(AbLegacyDriverOptions o) => new()
|
||||
{
|
||||
TimeoutSeconds = (int)o.Timeout.TotalSeconds,
|
||||
Transport = o.Transport,
|
||||
ProbeEnabled = o.Probe.Enabled,
|
||||
ProbeIntervalSeconds = (int)o.Probe.Interval.TotalSeconds,
|
||||
ProbeTimeoutSeconds = (int)o.Probe.Timeout.TotalSeconds,
|
||||
@@ -164,6 +178,7 @@
|
||||
ProbeAddress = string.IsNullOrWhiteSpace(ProbeAddress) ? null : ProbeAddress,
|
||||
},
|
||||
Timeout = TimeSpan.FromSeconds(TimeoutSeconds),
|
||||
Transport = Transport,
|
||||
ProbeTimeoutSeconds = AdminProbeTimeoutSeconds,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ public static class DriverFactoryBootstrap
|
||||
IDriverPrimaryRoleSource primaryRoleSource,
|
||||
ZB.MOM.WW.OtOpcUa.Core.Scripting.ScriptRootLogger? scriptRoot = null)
|
||||
{
|
||||
Driver.AbCip.AbCipDriverFactoryExtensions.Register(registry);
|
||||
Driver.AbCip.AbCipDriverFactoryExtensions.Register(registry, loggerFactory);
|
||||
Driver.AbLegacy.AbLegacyDriverFactoryExtensions.Register(registry, loggerFactory);
|
||||
Driver.Calculation.CalculationDriverFactoryExtensions.Register(registry, loggerFactory, scriptRoot);
|
||||
Driver.FOCAS.FocasDriverFactoryExtensions.Register(registry);
|
||||
|
||||
Reference in New Issue
Block a user