Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 81 additions & 62 deletions IpConnectWizardWindow.xaml
Original file line number Diff line number Diff line change
@@ -1,76 +1,95 @@
<Window x:Class="ArIED61850Tester.IpConnectWizardWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Add IEC 61850 IED" Height="470" Width="700"
WindowStartupLocation="CenterOwner" ResizeMode="NoResize"
Background="{StaticResource Bg}"
FontFamily="{StaticResource AppFontFamily}"
Icon="Assets/app-icon.ico">
<Grid Margin="22">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
Title="Add IEC 61850 IED" Width="700" MinWidth="640" MaxHeight="620"
SizeToContent="Height" WindowStartupLocation="CenterOwner"
ResizeMode="NoResize" ShowInTaskbar="False"
Background="{DynamicResource TaskDialogCanvas}"
FontFamily="{DynamicResource AppFontFamily}" Icon="Assets/app-icon.ico">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/IedTaskDialogStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>

<StackPanel Grid.Row="0" Margin="0,0,0,18">
<TextBlock Text="Add IEC 61850 IED" FontSize="25" FontWeight="SemiBold" Foreground="{StaticResource Ink}"/>
<TextBlock Text="Enter the actual relay endpoint. ArIED will establish ACSE/MMS, resolve the real IEDName, discover DataSets and RCBs, then open the signal selection wizard."
FontSize="13" Foreground="{StaticResource Muted}" TextWrapping="Wrap" Margin="0,6,0,0"/>
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
Focusable="False">
<Grid Margin="24,22,24,22">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<Border Grid.Row="1" Style="{StaticResource Card}" Padding="20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="14"/>
<ColumnDefinition Width="130"/>
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="Add IEC 61850 IED" Style="{StaticResource TaskDialogHeading}"/>
<TextBlock Margin="0,5,0,0" Style="{StaticResource TaskDialogSubtitle}"
Text="Enter the IED IP address to connect and discover available signals."/>
</StackPanel>

<StackPanel Grid.Row="0" Grid.Column="0">
<TextBlock Text="IED Runtime IP Address" FontSize="12.5" FontWeight="SemiBold" Foreground="{StaticResource Ink}" Margin="0,0,0,6"/>
<ComboBox x:Name="RelayIpBox" IsEditable="True" IsTextSearchEnabled="False"
ItemsSource="{Binding RecentRelayIps, RelativeSource={RelativeSource AncestorType=Window}}"
Text="{Binding RelayIpAddress, RelativeSource={RelativeSource AncestorType=Window}, UpdateSourceTrigger=LostFocus}"/>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="2">
<TextBlock Text="MMS Port" FontSize="12.5" FontWeight="SemiBold" Foreground="{StaticResource Ink}" Margin="0,0,0,6"/>
<TextBox Text="{Binding MmsPortText, RelativeSource={RelativeSource AncestorType=Window}, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
<Border Grid.Row="1" Margin="0,18,0,0" Style="{StaticResource TaskDialogCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="14"/>
<ColumnDefinition Width="128"/>
</Grid.ColumnDefinitions>

<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Background="#F8FBFF"
BorderBrush="#CFE0FF" BorderThickness="1" CornerRadius="15" Padding="14" Margin="0,18,0,0">
<StackPanel>
<TextBlock Text="Smart online discovery" FontSize="13" FontWeight="SemiBold" Foreground="{StaticResource Ink}"/>
<TextBlock Text="IEDName is read from the live IEC 61850 model. Signal choices saved for the same IEDName or endpoint are restored automatically, but new signals are never auto-selected."
TextWrapping="Wrap" FontSize="12.4" Foreground="{StaticResource Muted}" Margin="0,5,0,0"/>
<StackPanel Grid.Row="0" Grid.Column="0">
<TextBlock Text="IED IP Address" Style="{StaticResource TaskDialogFieldLabel}"
Margin="0,0,0,7"/>
<ComboBox x:Name="RelayIpBox" Height="40" MinWidth="0"
Foreground="{StaticResource TaskDialogInk}"
Background="{StaticResource TaskDialogCard}"
BorderBrush="{StaticResource TaskDialogBorder}"
IsEditable="True" IsTextSearchEnabled="False"
ToolTip="Enter a new IP address or choose a previously saved address"
ItemsSource="{Binding RecentRelayIps, RelativeSource={RelativeSource AncestorType=Window}}"
Text="{Binding RelayIpAddress, RelativeSource={RelativeSource AncestorType=Window}, UpdateSourceTrigger=LostFocus}"/>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="2">
<TextBlock Text="MMS Port" Style="{StaticResource TaskDialogFieldLabel}"
Margin="0,0,0,7"/>
<TextBox Height="40" VerticalContentAlignment="Center"
Padding="9,5" Foreground="{StaticResource TaskDialogInk}"
Background="{StaticResource TaskDialogCard}"
BorderBrush="{StaticResource TaskDialogBorder}"
ToolTip="IEC 61850 MMS normally uses TCP port 102"
Text="{Binding MmsPortText, RelativeSource={RelativeSource AncestorType=Window}, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Border>

<TextBlock x:Name="WizardStatusText" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
FontSize="12.5" FontWeight="SemiBold" Foreground="#E04F16" Margin="0,12,0,0"/>
<Border Grid.Row="1" Grid.ColumnSpan="3" Margin="0,16,0,0"
Background="{StaticResource TaskDialogHintSurface}"
BorderBrush="{StaticResource TaskDialogHintBorder}"
BorderThickness="1" CornerRadius="10" Padding="12,11">
<StackPanel>
<TextBlock Text="Smart discovery" FontSize="12.5" FontWeight="SemiBold"
Foreground="{StaticResource TaskDialogInk}"/>
<TextBlock Margin="0,3,0,0" Style="{StaticResource TaskDialogSubtitle}"
Text="Reads the live DataSets and RCBs, and restores saved signal choices."/>
</StackPanel>
</Border>

<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Background="#F8FAFC"
BorderBrush="{StaticResource Line}" BorderThickness="1" CornerRadius="16" Padding="14" Margin="0,18,0,0">
<TextBlock Text="Flow: TCP/TPKT/COTP → ACSE/MMS association → live model discovery → IEDName/LD resolution → DataSet/RCB audit → signal selection wizard."
TextWrapping="Wrap" FontSize="12.5" Foreground="{StaticResource Muted}"/>
</Border>
</Grid>
</Border>
<TextBlock x:Name="WizardStatusText" Grid.Row="2" Grid.ColumnSpan="3"
Margin="0,12,0,0" Style="{StaticResource TaskDialogError}"
AutomationProperties.LiveSetting="Assertive"/>
</Grid>
</Border>

<Grid Grid.Row="2" Margin="0,16,0,0">
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions>
<TextBlock Text="Only successful/saved endpoints appear in recent history." Foreground="{StaticResource Muted}" FontSize="12.2" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Content="Cancel" Style="{StaticResource SoftButton}" Click="Cancel_Click" Margin="0,0,8,0"/>
<Button Content="Connect &amp; Discover" Style="{StaticResource PrimaryButton}" Click="Connect_Click"/>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right"
Margin="0,18,0,0">
<Button Content="Cancel" Style="{StaticResource TaskDialogFooterButton}"
Click="Cancel_Click" IsCancel="True" Margin="0,0,10,0"/>
<Button Content="Connect &amp; Discover" Style="{StaticResource TaskDialogSubmitAction}"
MinWidth="174" MinHeight="38" IsDefault="True" Click="Connect_Click"/>
</StackPanel>
</Grid>
</Grid>
</ScrollViewer>
</Window>
32 changes: 24 additions & 8 deletions MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,18 +345,34 @@ await OpenSignalSelectionWizardAsync(
}
catch (Exception ex)
{
AddLog("ERROR", "SCL", $"Could not open {sourceLabel}: {ex.Message}");
SetStatus($"{sourceLabel}: SCL open failed. Diagnostics is marked with !.");
// Opening a valid SCL also opens a WPF action chooser. A broken XAML
// resource after model import is not an ARIEC61850 parser failure.
var presentationFailure = IsSclPresentationFailure(ex);
AddLog("ERROR", "SCL", $"Could not finish opening {sourceLabel}: {ex}");
SetStatus(presentationFailure
? $"{sourceLabel}: SCL action window failed to open; the model may already be loaded."
: $"{sourceLabel}: SCL open failed. Diagnostics is marked with !.");
MarkDiagnosticAlert();
MessageBox.Show(
this,
$"ARSAS could not open this SCL file through the ARIEC61850 engine.\n\n{ex.Message}",
"Open SCL",
MessageBoxButton.OK,
MessageBoxImage.Error);
var message = presentationFailure
? $"ARSAS could not display the SCL action window. The imported model may already be available in Engineering.\n\n{ex.GetBaseException().Message}\n\nSee Diagnostics for details."
: $"ARSAS could not open this SCL file through the ARIEC61850 engine.\n\n{ex.Message}";
MessageBox.Show(this, message, "Open SCL",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}

private static bool IsSclPresentationFailure(Exception exception)
{
for (Exception? cause = exception; cause is not null; cause = cause.InnerException)
{
if (cause is System.Windows.Markup.XamlParseException ||
cause is ResourceReferenceKeyNotFoundException ||
cause.Message.Contains("StaticResourceExtension", StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}

private void ApplySclWorkspaceToDevice(
Iec61850MonitorDevice device,
SclWorkspaceDocument document,
Expand Down
Loading