@@ -34,6 +34,22 @@ public static class S7DriverFactoryExtensions
|
||||
throw new InvalidOperationException(
|
||||
$"S7 driver config for '{driverInstanceId}' missing required Host");
|
||||
|
||||
// PR-S7-C3 — translate ScanGroupIntervalsMs (string -> int ms) into the runtime
|
||||
// string -> TimeSpan map. Skip any entry with a non-positive value rather than
|
||||
// throwing, so a config typo (e.g. 0 ms) degrades to "fall back to default
|
||||
// publishing interval" instead of breaking the whole driver init.
|
||||
IReadOnlyDictionary<string, TimeSpan>? scanGroupMap = null;
|
||||
if (dto.ScanGroupIntervalsMs is { Count: > 0 })
|
||||
{
|
||||
var built = new Dictionary<string, TimeSpan>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var kvp in dto.ScanGroupIntervalsMs)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(kvp.Key) || kvp.Value <= 0) continue;
|
||||
built[kvp.Key] = TimeSpan.FromMilliseconds(kvp.Value);
|
||||
}
|
||||
if (built.Count > 0) scanGroupMap = built;
|
||||
}
|
||||
|
||||
var options = new S7DriverOptions
|
||||
{
|
||||
Host = dto.Host!,
|
||||
@@ -57,6 +73,7 @@ public static class S7DriverFactoryExtensions
|
||||
fallback: TsapMode.Auto),
|
||||
LocalTsap = dto.LocalTsap,
|
||||
RemoteTsap = dto.RemoteTsap,
|
||||
ScanGroupIntervals = scanGroupMap,
|
||||
};
|
||||
|
||||
return new S7Driver(options, driverInstanceId);
|
||||
@@ -72,7 +89,8 @@ public static class S7DriverFactoryExtensions
|
||||
tagName: t.Name),
|
||||
Writable: t.Writable ?? true,
|
||||
StringLength: t.StringLength ?? 254,
|
||||
WriteIdempotent: t.WriteIdempotent ?? false);
|
||||
WriteIdempotent: t.WriteIdempotent ?? false,
|
||||
ScanGroup: string.IsNullOrWhiteSpace(t.ScanGroup) ? null : t.ScanGroup);
|
||||
|
||||
private static T ParseEnum<T>(string? raw, string driverInstanceId, string field,
|
||||
string? tagName = null, T? fallback = null) where T : struct, Enum
|
||||
@@ -122,6 +140,15 @@ public static class S7DriverFactoryExtensions
|
||||
|
||||
/// <summary>Optional 16-bit remote TSAP override. Required (with <see cref="LocalTsap"/>) when <c>TsapMode = Other</c>.</summary>
|
||||
public ushort? RemoteTsap { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// PR-S7-C3 — optional scan-group → publishing-interval (ms) map. Tags carrying
|
||||
/// a matching <see cref="S7TagDto.ScanGroup"/> string poll at the configured
|
||||
/// rate; tags with no group, or with a group not present here, fall back to
|
||||
/// the subscription default. Group names are matched case-insensitively. See
|
||||
/// <c>docs/v2/s7.md</c> "Per-tag scan groups" section.
|
||||
/// </summary>
|
||||
public Dictionary<string, int>? ScanGroupIntervalsMs { get; init; }
|
||||
}
|
||||
|
||||
internal sealed class S7TagDto
|
||||
@@ -132,6 +159,14 @@ public static class S7DriverFactoryExtensions
|
||||
public bool? Writable { get; init; }
|
||||
public int? StringLength { get; init; }
|
||||
public bool? WriteIdempotent { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// PR-S7-C3 — optional scan-group identifier. Resolved against
|
||||
/// <see cref="S7DriverConfigDto.ScanGroupIntervalsMs"/> at subscribe time.
|
||||
/// Null / empty = no group (legacy behaviour, falls back to subscription
|
||||
/// default publishing interval).
|
||||
/// </summary>
|
||||
public string? ScanGroup { get; init; }
|
||||
}
|
||||
|
||||
internal sealed class S7ProbeDto
|
||||
|
||||
Reference in New Issue
Block a user