From e846d32e47abcd884dca1b99ac6e0c7eb42e5853 Mon Sep 17 00:00:00 2001 From: masarray Date: Mon, 20 Jul 2026 15:43:59 +0700 Subject: [PATCH 1/2] Allow downloading available relay fault-record files --- Services/FaultRecordTransferClient.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Services/FaultRecordTransferClient.cs b/Services/FaultRecordTransferClient.cs index eb4aee3b0..6fa93a4b7 100644 --- a/Services/FaultRecordTransferClient.cs +++ b/Services/FaultRecordTransferClient.cs @@ -103,7 +103,9 @@ public async Task DownloadAsync( MaximumTotalBytes = 1024L * 1024L * 1024L, MaximumFileBytes = 512L * 1024L * 1024L, MaximumReadOperationsPerFile = 100_000, - RequireCompleteRecord = true, + // Completeness describes COMTRADE companion coverage; it must not block + // MMS FileOpen/FileRead of files that the IED actually exposes. + RequireCompleteRecord = false, RequireDeclaredSizeMatch = false }, progress, From 6cdec24151e29d63944ef1f7578af511f28eaf08 Mon Sep 17 00:00:00 2001 From: masarray Date: Mon, 20 Jul 2026 15:44:58 +0700 Subject: [PATCH 2/2] Enable MMS download for partial and single-file fault records --- FaultRecordWindow.xaml.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/FaultRecordWindow.xaml.cs b/FaultRecordWindow.xaml.cs index 28c865783..8c11ed044 100644 --- a/FaultRecordWindow.xaml.cs +++ b/FaultRecordWindow.xaml.cs @@ -90,7 +90,7 @@ public double ProgressValue private set => Set(ref _progressValue, Math.Clamp(value, 0d, 100d)); } - public bool CanDownload => !IsBusy && Records.Any(row => row.IsSelected && row.Record.IsComplete); + public bool CanDownload => !IsBusy && Records.Any(row => row.IsSelected && row.Record.Files.Count > 0); public string SelectionSummary { @@ -139,7 +139,7 @@ private async Task ScanAsync() StatusText = catalog.Records.Count == 0 ? "No supported fault-record files were found. Try a known remote directory such as COMTRADE or DR." - : $"{catalog.Summary} Select one or more complete records to download."; + : $"{catalog.Summary} Select one or more available records to download; partial companion sets remain downloadable."; if (catalog.Diagnostics.Count > 0) StatusText += $" {catalog.Diagnostics.Count} bounded browse diagnostic(s) were reported."; @@ -183,11 +183,11 @@ private async void Download_Click(object sender, RoutedEventArgs e) return; var selected = Records - .Where(row => row.IsSelected && row.Record.IsComplete) + .Where(row => row.IsSelected && row.Record.Files.Count > 0) .ToArray(); if (selected.Length == 0) { - StatusText = "Select at least one complete COMTRADE record."; + StatusText = "Select at least one record that contains an available remote file."; return; } @@ -344,7 +344,13 @@ public sealed class FaultRecordRow : INotifyPropertyChanged public FaultRecordRow(Iec61850FaultRecordSet record) { Record = record ?? throw new ArgumentNullException(nameof(record)); - _status = record.IsComplete ? "Ready" : "Incomplete"; + _status = record.Files.Count == 0 + ? "Unavailable" + : record.IsComplete + ? "Ready" + : "Partial"; + if (!record.IsComplete && record.Files.Count > 0) + _detail = $"Available file(s) can be downloaded; COMTRADE companion coverage: {record.Completeness}."; } public event PropertyChangedEventHandler? PropertyChanged; @@ -355,7 +361,10 @@ public FaultRecordRow(Iec61850FaultRecordSet record) public string Completeness => Record.Completeness; public string ModifiedText => Record.LastModifiedUtc?.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) ?? "-"; public string SizeText => Record.HasUnknownSize ? "Unknown" : FormatBytes(Record.KnownSizeBytes); - public string FilesText => string.Join(", ", Record.Files.Select(file => file.Extension.TrimStart('.').ToUpperInvariant())); + public string FilesText => string.Join(", ", Record.Files.Select(file => + string.IsNullOrWhiteSpace(file.Extension) + ? "PACKAGE" + : file.Extension.TrimStart('.').ToUpperInvariant())); public bool IsSelected {