From 2d20d67b30cbc52f297923bfe323f16091c2348d Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 4 Sep 2026 14:20:54 +0700 Subject: [PATCH 1/7] fix: add Static DataSet mode with safe MMS fallback --- Services/Iec61850MonitoringModeRegistry.cs | 61 ++++++++++++++++++---- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/Services/Iec61850MonitoringModeRegistry.cs b/Services/Iec61850MonitoringModeRegistry.cs index 5f13bca15..2bb514a45 100644 --- a/Services/Iec61850MonitoringModeRegistry.cs +++ b/Services/Iec61850MonitoringModeRegistry.cs @@ -11,32 +11,61 @@ public static class Iec61850MonitoringModeRegistry { private sealed class DeviceModeState { - public bool StaticDataSetReportOnly { get; set; } + public bool StaticDataSetMode { get; set; } + public bool StrictReportOnly { get; set; } public bool PreviousDynamicDataSetWrites { get; set; } public bool HasPreviousDynamicDataSetWrites { get; set; } } private static readonly ConditionalWeakTable States = new(); + public static bool IsStaticDataSetMode(Iec61850MonitorDevice device) + { + ArgumentNullException.ThrowIfNull(device); + return States.TryGetValue(device, out var state) && state.StaticDataSetMode; + } + public static bool IsStaticDataSetReportOnly(Iec61850MonitorDevice device) { ArgumentNullException.ThrowIfNull(device); - return States.TryGetValue(device, out var state) && state.StaticDataSetReportOnly; + return States.TryGetValue(device, out var state) && + state.StaticDataSetMode && + state.StrictReportOnly; } - public static void UseStaticDataSetReportOnly(Iec61850MonitorDevice device) + /// + /// Selects the Static DataSet workflow while retaining bounded MMS reads for the + /// initial live image and for DataSet members that cannot be safely supplied by a + /// configured report. Dynamic DataSet writes remain disabled, so the IED's existing + /// engineering configuration is never modified merely to obtain readable values. + /// + public static void UseStaticDataSetWithMmsFallback(Iec61850MonitorDevice device) { ArgumentNullException.ThrowIfNull(device); var state = States.GetOrCreateValue(device); lock (state) { - if (!state.StaticDataSetReportOnly) - { - state.PreviousDynamicDataSetWrites = device.AllowDynamicDataSetWrites; - state.HasPreviousDynamicDataSetWrites = true; - } + CapturePreviousDynamicWriteSetting(device, state); + state.StaticDataSetMode = true; + state.StrictReportOnly = false; + device.AllowDynamicDataSetWrites = false; + } + } - state.StaticDataSetReportOnly = true; + /// + /// Strict report-only variant retained for explicit engineering/diagnostic use. + /// Process values that cannot be delivered through configured static reporting are + /// intentionally left unavailable in this mode. + /// + public static void UseStaticDataSetReportOnly(Iec61850MonitorDevice device) + { + ArgumentNullException.ThrowIfNull(device); + var state = States.GetOrCreateValue(device); + lock (state) + { + CapturePreviousDynamicWriteSetting(device, state); + state.StaticDataSetMode = true; + state.StrictReportOnly = true; device.AllowDynamicDataSetWrites = false; } } @@ -47,7 +76,8 @@ public static void UseHybrid(Iec61850MonitorDevice device) var state = States.GetOrCreateValue(device); lock (state) { - state.StaticDataSetReportOnly = false; + state.StaticDataSetMode = false; + state.StrictReportOnly = false; if (state.HasPreviousDynamicDataSetWrites) { device.AllowDynamicDataSetWrites = state.PreviousDynamicDataSetWrites; @@ -55,4 +85,15 @@ public static void UseHybrid(Iec61850MonitorDevice device) } } } + + private static void CapturePreviousDynamicWriteSetting( + Iec61850MonitorDevice device, + DeviceModeState state) + { + if (state.StaticDataSetMode || state.HasPreviousDynamicDataSetWrites) + return; + + state.PreviousDynamicDataSetWrites = device.AllowDynamicDataSetWrites; + state.HasPreviousDynamicDataSetWrites = true; + } } From 99312035062de619c5f2d7cdee2204935663e2c4 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 4 Sep 2026 14:21:15 +0700 Subject: [PATCH 2/7] fix: keep Static DataSet values readable with bounded MMS --- MainWindow.SharedSclWorkspace.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/MainWindow.SharedSclWorkspace.cs b/MainWindow.SharedSclWorkspace.cs index 0b602b1b7..34171a580 100644 --- a/MainWindow.SharedSclWorkspace.cs +++ b/MainWindow.SharedSclWorkspace.cs @@ -37,13 +37,14 @@ private enum SclSignalSelectionMode private void ApplyStaticDataSetSelection(Iec61850MonitorDevice device) { - // Static DataSet is a protocol-authority mode, not a request to monitor the - // whole IED and then opportunistically prefer reports. First make sure every - // ARIEC-owned DataSet member is present in the workspace, then select only - // runtime signals that carry an explicit static DataSet identity. + // Static DataSet remains the source of truth for WHAT is monitored. Acquisition + // prefers the IED's configured BRCB/URCB, while bounded MMS reads remain available + // for the initial image and for DataSet members whose report mapping/projection is + // incomplete. Dynamic DataSet writes stay disabled so monitoring never rewrites the + // IED configuration merely to obtain IEDScout-equivalent readable values. var merge = Iec61850DataSetSignalInventoryService.EnsureMandatorySignals(device); RegisterRecoveredDataSetSignals(device, merge); - Iec61850MonitoringModeRegistry.UseStaticDataSetReportOnly(device); + Iec61850MonitoringModeRegistry.UseStaticDataSetWithMmsFallback(device); device.BeginBulkSignalSelection(); try @@ -64,7 +65,7 @@ private void ApplyStaticDataSetSelection(Iec61850MonitorDevice device) AddLog( "INFO", device.Name, - $"Static DataSet report-only authority selected: {device.SelectedLiveSignalCount} runtime DataSet signal(s); cyclic MMS process polling and dynamic DataSet writes are disabled for this monitoring mode."); + $"Static DataSet authority selected: {device.SelectedLiveSignalCount} runtime DataSet signal(s); configured RCB reporting is preferred, bounded MMS read fallback remains available for initial/uncovered values, and dynamic DataSet writes are disabled."); } private void ClearSharedSignalSelection(Iec61850MonitorDevice device) From c4869f6ef1a77dab29c02dfe122b4cbdfdf0b800 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 4 Sep 2026 14:21:32 +0700 Subject: [PATCH 3/7] ux: describe Static DataSet monitoring as DataSet-authoritative --- MainWindow.SclQuickActions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MainWindow.SclQuickActions.cs b/MainWindow.SclQuickActions.cs index e943ea089..4055584fd 100644 --- a/MainWindow.SclQuickActions.cs +++ b/MainWindow.SclQuickActions.cs @@ -111,7 +111,7 @@ internal async Task OpenIedWorkspaceActionsAsync(Iec61850MonitorDevice device) ApplyStaticDataSetSelection(device); if (device.SelectedLiveSignalCount == 0) { - SetStatus($"{device.Name}: Static DataSet selected, but no report-authoritative process leaf is available to monitor."); + SetStatus($"{device.Name}: Static DataSet selected, but no DataSet-authoritative process signal is available to monitor."); return; } From 1e88688d00f0348183d4d158ac43b9918c175e01 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 4 Sep 2026 14:21:51 +0700 Subject: [PATCH 4/7] ux: explain Static DataSet RCB preference and MMS fallback --- SclSignalSelectionModeWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SclSignalSelectionModeWindow.xaml b/SclSignalSelectionModeWindow.xaml index 1cc97f2c2..8f889f9fc 100644 --- a/SclSignalSelectionModeWindow.xaml +++ b/SclSignalSelectionModeWindow.xaml @@ -50,7 +50,7 @@