feat(modbus-rtu): bind Transport mode on options/DTO/factory (string-enum guard)
Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
@@ -130,6 +130,14 @@ public sealed class ModbusDriverOptions
|
||||
/// </summary>
|
||||
public MelsecFamily MelsecSubFamily { get; init; } = MelsecFamily.Q_L_iQR;
|
||||
|
||||
/// <summary>
|
||||
/// Wire transport selector. <see cref="ModbusTransportMode.Tcp"/> (default) is the
|
||||
/// historical Modbus TCP/MBAP framing. <see cref="ModbusTransportMode.RtuOverTcp"/>
|
||||
/// frames Modbus RTU PDUs (CRC16, no MBAP header) over the same TCP socket — for
|
||||
/// serial-to-Ethernet gateways that bridge RS-485 without re-encapsulating to MBAP.
|
||||
/// </summary>
|
||||
public ModbusTransportMode Transport { get; init; } = ModbusTransportMode.Tcp;
|
||||
|
||||
/// <summary>
|
||||
/// When <c>true</c>, the driver suppresses redundant writes: if the most recent
|
||||
/// successful write to a tag carried value V and a new write of V arrives, the second
|
||||
|
||||
@@ -74,6 +74,8 @@ public static class ModbusDriverFactoryExtensions
|
||||
: ParseEnum<ModbusFamily>(dto.Family, "<driver-level>", driverInstanceId, "Family"),
|
||||
MelsecSubFamily = dto.MelsecSubFamily is null ? MelsecFamily.Q_L_iQR
|
||||
: ParseEnum<MelsecFamily>(dto.MelsecSubFamily, "<driver-level>", driverInstanceId, "MelsecSubFamily"),
|
||||
Transport = dto.Transport is null ? ModbusTransportMode.Tcp
|
||||
: ParseEnum<ModbusTransportMode>(dto.Transport, "<driver-level>", driverInstanceId, "Transport"),
|
||||
AutoProhibitReprobeInterval = dto.AutoProhibitReprobeMs is { } reprobeMs ? TimeSpan.FromMilliseconds(reprobeMs) : null,
|
||||
AutoReconnect = dto.AutoReconnect ?? true,
|
||||
// v3: the deploy artifact (Wave C) populates rawTags with the cluster's authored raw Modbus
|
||||
@@ -159,6 +161,8 @@ public static class ModbusDriverFactoryExtensions
|
||||
public string? Family { get; init; }
|
||||
/// <summary>Gets or sets the Melsec subfamily.</summary>
|
||||
public string? MelsecSubFamily { get; init; }
|
||||
/// <summary>Gets or sets the wire transport mode (Tcp / RtuOverTcp). Null defaults to Tcp.</summary>
|
||||
public string? Transport { get; init; }
|
||||
/// <summary>Gets or sets the automatic prohibition reprobei interval in milliseconds.</summary>
|
||||
public int? AutoProhibitReprobeMs { get; init; }
|
||||
/// <summary>Gets or sets a value indicating whether automatic reconnection is enabled.</summary>
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;
|
||||
|
||||
public sealed class ModbusTransportConfigRoundTripTests
|
||||
{
|
||||
// Mirrors the AdminUI ModbusDriverForm serializer: camelCase + string enums.
|
||||
private static readonly JsonSerializerOptions _adminOpts = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void Transport_serializes_as_a_string_not_a_number()
|
||||
{
|
||||
var opts = new ModbusDriverOptions { Host = "10.20.0.50", Port = 4001, Transport = ModbusTransportMode.RtuOverTcp };
|
||||
var json = JsonSerializer.Serialize(opts, _adminOpts);
|
||||
json.ShouldContain("\"transport\":\"RtuOverTcp\"");
|
||||
json.ShouldNotContain("\"transport\":1", Case.Sensitive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Factory_binds_RtuOverTcp_from_string_config()
|
||||
{
|
||||
const string json = """{ "host": "10.20.0.50", "port": 4001, "transport": "RtuOverTcp" }""";
|
||||
using var driver = ModbusDriverFactoryExtensions.CreateInstance("mb-rtu", json);
|
||||
var opts = (ModbusDriverOptions)typeof(ModbusDriver)
|
||||
.GetField("_options", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!
|
||||
.GetValue(driver)!;
|
||||
opts.Transport.ShouldBe(ModbusTransportMode.RtuOverTcp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Factory_defaults_Transport_to_Tcp_when_omitted()
|
||||
{
|
||||
const string json = """{ "host": "10.0.0.10" }""";
|
||||
using var driver = ModbusDriverFactoryExtensions.CreateInstance("mb-tcp", json);
|
||||
var opts = (ModbusDriverOptions)typeof(ModbusDriver)
|
||||
.GetField("_options", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)!
|
||||
.GetValue(driver)!;
|
||||
opts.Transport.ShouldBe(ModbusTransportMode.Tcp);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user