HMI.Util/Alarm/AlarmUtil.cs
@@ -20,7 +20,7 @@ public event EventHandler<LoadMsg> LoadMessageAppend; private static ILog log = LogManager.GetLogger("AlarmHelper"); internal static ILog log = LogManager.GetLogger("AlarmHelper"); internal AlarmHelper() { @@ -353,10 +353,12 @@ public static void Init() { AlarmHelper.log.Info("AlarmUtil initing..."); Instance = new AlarmHelper(); Instance.LoadMessageAppend += Instance_LoadMessageAppend; ; Instance.InitInstance(); Instance.OnAlarm += Instance_OnAlarm; AlarmHelper.log.Info("AlarmUtil inited finished."); } private static void Instance_LoadMessageAppend(object sender, LoadMsg e) Plugin.BurnIn/BurnInUI.xaml.cs
@@ -128,12 +128,6 @@ } if (EventCase == 8) { IsRunning = false; return; } if (EventCase != 10014) return; if (MethodCode == 0) @@ -155,6 +149,10 @@ { /// 更新生产状态 produceStatus = strData; if (string.Equals(strData, "stop", StringComparison.OrdinalIgnoreCase)) { IsRunning = false; } return; } } @@ -391,7 +389,7 @@ log.Info("总停止按钮按下"); testResultView.StopTest(); /// 已经加了WaitForExit,这里可以改为false IsRunning = false; //IsRunning = false; } catch (Exception ex) { Plugin.BurnIn/DataTable.xaml
@@ -16,6 +16,7 @@ BorderBrush="Black" BorderThickness="1" x:Name="control" PreviewMouseRightButtonDown="control_PreviewMouseRightButtonDown" Loaded="UserControl_Loaded" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Resources> Plugin.BurnIn/DataTable.xaml.cs
@@ -1,4 +1,5 @@ using HMI.Base; using HMI.Core.Manager; using HMI.Core.Setting; using HMI.Core.Util; using HMI.LogUtil; @@ -584,12 +585,12 @@ GetSingleCell(cellIndex).SetInfos(new Info { step = values[0], value = values[1], limitUp = values[2], limitDown = values[3], unit = values[4], result = values[5], updateTime = values[6] value = values[2], unit = values[3], limitUp = values[4], limitDown = values[5], result = values[6], updateTime = values[7] }); }); //session.Send("1"); @@ -599,17 +600,10 @@ { infoTable.UpdateNumber(infoTable.okCount + ok, infoTable.ngCount + ng); if (ParamSetting.ProbeByModel) { } else { IniFileHelper.WriteIniData($"Oven_{index}", "Pass", infoTable.okCount.ToString(), this.CountIniPath); IniFileHelper.WriteIniData($"Oven_{index}", "Fail", infoTable.ngCount.ToString(), this.CountIniPath); } } /// <summary> @@ -883,5 +877,52 @@ string key = $"StationHMI.UUTHMI[{this.index}].Abort"; parent.executionWrapper?.SetStationGlobalValue(key, 0, true); } private void MenuItem_Click(object sender, RoutedEventArgs e) { string manualDebugSeq = ParameterManager.GetCommonParameterByName("ManualDebugSeqPath")?.Value; if (string.IsNullOrEmpty(manualDebugSeq)) { MsgBoxHelper2.Error("请先设置手动调试序列路径[ManualDebugSeqPath]!"); return; } string modelPath = parent.testModelFile; var win = new ManualDebugWindow(manualDebugSeq, modelPath, true, cells, mainGrid.Columns) { CellCount = cells.Length, Title = $"{this.title}手动调试", Owner = Window.GetWindow(this), OvenIndex = this.index, OvenName = this.title, CellName = this.title, CellIndex = -1 }; win.ShowDialog(); } private void ContextMenu_Closed(object sender, RoutedEventArgs e) { this.ContextMenu = null; } private void control_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (!parent.inManualDebugMode) { return; } ContextMenu contextMenu = new ContextMenu(); contextMenu.Closed += ContextMenu_Closed; var item = new MenuItem { IsCheckable = false, Name = "manualDebugItem", Header = this.lang("手动调试"), }; item.Click += MenuItem_Click; contextMenu.Items.Add(item); this.ContextMenu = contextMenu; } } } Plugin.BurnIn/ManualDebug/ManualCell.xaml
New file @@ -0,0 +1,33 @@ <UserControl x:Class="Plugin.BurnIn.ManualCell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Plugin.BurnIn" xmlns:pu="https://opensource.panuon.com/wpf-ui" mc:Ignorable="d" Padding="5" MaxHeight="80" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Style> <Style TargetType="UserControl"> <Style.Triggers> <DataTrigger Binding="{Binding Selected}" Value="True"> <Setter Property="Background" Value="{DynamicResource SuccessColor}"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> </Style.Triggers> </Style> </UserControl.Style> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock FontSize="20" FontWeight="Bold" Text="{Binding Title}"/> <pu:Switch Grid.Row="1" FontSize="18" BoxHeight="20" Cursor="Hand" Content="关" CheckedBackground="Green" Background="Red" CheckedContent="开" IsChecked="{Binding Selected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> </Grid> </UserControl> Plugin.BurnIn/ManualDebug/ManualCell.xaml.cs
New file @@ -0,0 +1,47 @@ using CommunityToolkit.Mvvm.ComponentModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace Plugin.BurnIn { /// <summary> /// ManualCell.xaml 的交互逻辑 /// </summary> [ObservableObject] public partial class ManualCell : UserControl { [ObservableProperty] private string title; [ObservableProperty] private bool selected; [ObservableProperty] private int index; public event EventHandler SelectedChanged; public ManualCell() { this.DataContext = this; InitializeComponent(); } partial void OnSelectedChanged(bool value) { SelectedChanged?.Invoke(this, new EventArgs()); } } } Plugin.BurnIn/ManualDebug/ManualDebug.xaml
New file @@ -0,0 +1,212 @@ <UserControl x:Class="Plugin.BurnIn.ManualDebug" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Plugin.BurnIn" xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" mc:Ignorable="d" x:Name="self" MinHeight="400" MinWidth="500"> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Util.ManualDebug;component/ManualDebugStyle.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid x:Name="CellSelectBorder"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Border Background="{StaticResource TsPanelBrush}" Margin="0,0,10,5" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="4" Padding="15"> <StackPanel> <TextBlock Text="穴位选择" FontSize="14" FontWeight="SemiBold" Foreground="{StaticResource PrimaryBrush}" Margin="0,0,0,15"/> <UniformGrid IsEnabled="False" x:Name="CellGrid" dp:UniformGridHelper.InnerBorder="1" dp:UniformGridHelper.InnerBorderBrush="{StaticResource BorderBrush}"> </UniformGrid> </StackPanel> </Border> <Border Grid.Row="1" Background="{StaticResource TsPanelBrush}" Margin="0,5,10,0" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="4" Padding="15"> <StackPanel> <TextBlock Text="穴位测试结果" FontSize="14" FontWeight="SemiBold" Foreground="{StaticResource PrimaryBrush}" Margin="0,0,0,15"/> <UniformGrid IsEnabled="False" x:Name="CellResultGrid" dp:UniformGridHelper.InnerBorder="1" dp:UniformGridHelper.InnerBorderBrush="{StaticResource BorderBrush}"> </UniformGrid> </StackPanel> </Border> </Grid> <Grid Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="5"/> <RowDefinition Height="*"/> <RowDefinition Height="5"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <WindowsFormsHost x:Name="host" Visibility="Collapsed"></WindowsFormsHost> <!-- 按钮和状态区域 --> <Border Grid.Row="0" Background="{StaticResource TsPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="4" Padding="15"> <StackPanel> <TextBlock Text="手动调试控制" FontSize="14" FontWeight="SemiBold" Foreground="{StaticResource PrimaryBrush}" Margin="0,0,0,15"/> <WrapPanel x:Name="btnPanel"> </WrapPanel> </StackPanel> </Border> <!-- 分隔条1 --> <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" Background="Transparent" Cursor="SizeNS"/> <!-- TX/RX 数据区域 --> <Border Grid.Row="2" Background="{StaticResource TsPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="4" Padding="10"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" Margin="0,0,0,10"> <TextBlock Text="测试数据" FontSize="14" FontWeight="SemiBold" Foreground="{StaticResource PrimaryBrush}" VerticalAlignment="Center"/> <Button Content="清空" Style="{StaticResource ActionButtonStyle}" Margin="15,0,0,0" Click="OnClearClick"/> </StackPanel> <DataGrid x:Name="DataGridComm" Grid.Row="1" ItemsSource="{Binding TestData,ElementName=self}"> <DataGrid.Columns> <DataGridTextColumn Header="测试项" Binding="{Binding Name}" Width="120" IsReadOnly="True"/> <DataGridTextColumn Header="收" Binding="{Binding Receive}" Width="*" IsReadOnly="True"/> <DataGridTextColumn Header="发" Binding="{Binding Send}" Width="*" IsReadOnly="True"/> <DataGridTextColumn Header="单位" Binding="{Binding Unit}" Width="60" IsReadOnly="True"/> <DataGridTextColumn Header="上限" Binding="{Binding UpperLimit}" Width="80" IsReadOnly="True"/> <DataGridTextColumn Header="下限" Binding="{Binding LowerLimit}" Width="80" IsReadOnly="True"/> <DataGridTextColumn Header="结果" Binding="{Binding Result}" Width="70" IsReadOnly="True"/> <DataGridTextColumn Header="时间" Binding="{Binding Time}" Width="90" IsReadOnly="True"/> </DataGrid.Columns> <DataGrid.RowStyle> <Style TargetType="DataGridRow"> <Style.Triggers> <DataTrigger Value="True"> <DataTrigger.Binding> <MultiBinding Converter="{x:Static local:ResultFailedConverter.Instance}"> <Binding Path="Result"/> </MultiBinding> </DataTrigger.Binding> <Setter Property="Background" Value="#FFE0E0"/> <Setter Property="Foreground" Value="#C53030"/> </DataTrigger> </Style.Triggers> </Style> </DataGrid.RowStyle> </DataGrid> </Grid> </Border> <!-- 分隔条2 --> <GridSplitter Grid.Row="3" Height="5" HorizontalAlignment="Stretch" Background="Transparent" Cursor="SizeNS"/> <!-- 日志区域 --> <Border Grid.Row="4" Background="{StaticResource TsPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="4" Padding="10"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" Margin="0,0,0,8"> <TextBlock Text="日志" FontSize="14" FontWeight="SemiBold" Foreground="{StaticResource PrimaryBrush}" VerticalAlignment="Center"/> <Button Content="清空日志" Style="{StaticResource ActionButtonStyle}" Margin="15,0,0,0" Click="OnClearLogClick"/> </StackPanel> <RichTextBox x:Name="LogRichTextBox" Grid.Row="1" IsReadOnly="True" VerticalScrollBarVisibility="Auto" FontFamily="Consolas" FontSize="11" BorderThickness="1" BorderBrush="Black" Padding="4"/> </Grid> </Border> </Grid> <Border Background="#AAFFFFFF" Grid.ColumnSpan="2" x:Name="mask"> <TextBlock Text="初始化中..." FontSize="16" FontWeight="Bold" Foreground="{StaticResource PrimaryBrush}" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> </Grid> <StatusBar FontSize="14" Grid.Row="1"> <StatusBar.ItemsPanel> <ItemsPanelTemplate> <DockPanel LastChildFill="False"/> </ItemsPanelTemplate> </StatusBar.ItemsPanel> <StatusBarItem DockPanel.Dock="Left"> <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="8"> <StackPanel Orientation="Horizontal"> <Ellipse Width="10" Height="10"> <Ellipse.Style> <Style TargetType="Ellipse"> <Setter Property="Fill" Value="LightGray"/> <Style.Triggers> <DataTrigger Binding="{Binding TcpServerStatus,ElementName=self}" Value="ERROR"> <Setter Property="Fill" Value="Red"/> </DataTrigger> <DataTrigger Binding="{Binding TcpServerStatus,ElementName=self}" Value="RUNNING"> <Setter Property="Fill" Value="Green"/> </DataTrigger> </Style.Triggers> </Style> </Ellipse.Style> </Ellipse> <TextBlock Text="{Binding TcpServerInfo,ElementName=self}"/> <Button Padding="0" Margin="0" BorderThickness="0" Command="{Binding StartTcpServerCommand,ElementName=self}">🔄</Button> </StackPanel> </StackPanel> </StatusBarItem> </StatusBar> </Grid> </UserControl> Plugin.BurnIn/ManualDebug/ManualDebug.xaml.cs
New file @@ -0,0 +1,691 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using HMI.Core.Util; using HMI.UI.DpUtil; using NationalInstruments.TestStand.Interop.API; using Plugin.BurnIn.Model; using Plugin.TsSupport; using SuperSocket.SocketBase.Config; using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Media; namespace Plugin.BurnIn { public class BtnConfig { public string Title { get; set; } public string Name { get; set; } } // 结果失败判断转换器(支持不区分大小写) public class ResultFailedConverter : IMultiValueConverter { public static readonly ResultFailedConverter Instance = new ResultFailedConverter(); public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values.Length > 0 && values[0] is string) { string result = (string)values[0]; string upper = result.ToUpperInvariant(); return upper == "NG" || upper == "FAIL"; } return false; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } // 日志级别枚举 public enum LogLevel { Debug = 0, Info = 1, Warn = 2, Error = 3 } [ObservableObject] public partial class ManualDebug : UserControl { public static readonly DependencyProperty OvenNameProperty = DependencyProperty.Register( "OvenName", typeof(string), typeof(ManualDebug), new PropertyMetadata("")); public static readonly DependencyProperty CellNameProperty = DependencyProperty.Register( "CellName", typeof(string), typeof(ManualDebug), new PropertyMetadata("")); public static readonly DependencyProperty OvenIndexProperty = DependencyProperty.Register( "OvenIndex", typeof(int), typeof(ManualDebug), new PropertyMetadata(0)); public static readonly DependencyProperty CellIndexProperty = DependencyProperty.Register( "CellIndex", typeof(int), typeof(ManualDebug), new PropertyMetadata(-1)); public static readonly DependencyProperty CellCountProperty = DependencyProperty.Register( "CellCount", typeof(int), typeof(ManualDebug), new PropertyMetadata(0)); public string OvenName { get { return (string)GetValue(OvenNameProperty); } set { SetValue(OvenNameProperty, value); } } public string CellName { get { return (string)GetValue(CellNameProperty); } set { SetValue(CellNameProperty, value); } } public int OvenIndex { get { return (int)GetValue(OvenIndexProperty); } set { SetValue(OvenIndexProperty, value); } } public int CellIndex { get { return (int)GetValue(CellIndexProperty); } set { SetValue(CellIndexProperty, value); } } public int CellCount { get { return (int)GetValue(CellCountProperty); } set { SetValue(CellCountProperty, value); } } public ObservableCollection<TestDataItem> TestData { get; private set; } = new ObservableCollection<TestDataItem>(); private Dictionary<string, StatusBtn> btnCache = new Dictionary<string, StatusBtn>(); // 日志级别颜色 private readonly SolidColorBrush _debugBrush; private readonly SolidColorBrush _infoBrush; private readonly SolidColorBrush _warnBrush; private readonly SolidColorBrush _errorBrush; private ITestExecutionWrapper executionWrapper; private TcpServer tcpServer; public string seqPath { get; set; } public string modelPath { get; set; } = "C:\\Program Files\\National Instruments\\TestStand 2020\\Components\\Models\\TestStandModels\\ParallelModel.seq"; [ObservableProperty] private string tcpServerStatus; [ObservableProperty] private string tcpServerInfo; public ManualDebug() { _debugBrush = new SolidColorBrush(Color.FromRgb(0x71, 0x80, 0x8A)); // 灰色 _infoBrush = new SolidColorBrush(Colors.Black); _warnBrush = new SolidColorBrush(Color.FromRgb(0xD6, 0x9E, 0x2E)); // 橙黄色 _errorBrush = new SolidColorBrush(Color.FromRgb(0xC5, 0x30, 0x30)); // 红色 this.Loaded += ManualDebug_Loaded; InitializeComponent(); RefreshButtons(null); } public void HideCells(bool flag) { CellSelectBorder.Visibility = flag ? Visibility.Collapsed : Visibility.Visible; } private List<ManualCell> Cells = new List<ManualCell>(); private List<StatusCell> StatusCells = new List<StatusCell>(); public void RefreshGrid(SingleCell[] cells) { if (cells != null) { int i = 0; foreach (var cell in cells) { var mCell = new ManualCell { Title = cell.title, Index = cell.index }; mCell.SelectedChanged += MCell_SelectedChanged; Cells.Add(mCell); CellGrid.Children.Add(mCell); var sCell = new StatusCell { Title = cell.title, Index = cell.index }; StatusCells.Add(sCell); CellResultGrid.Children.Add(sCell); BindingOperations.SetBinding(sCell, StatusCell.StatusProperty, new Binding(nameof(ManualCell.Selected)) { Source = mCell, Mode = BindingMode.OneWay, //UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, Converter = CellStatusConverter.Instance }); } UniformGridHelper.RefreshGridInnerBorder(CellGrid); UniformGridHelper.RefreshGridInnerBorder(CellResultGrid); } } private void MCell_SelectedChanged(object sender, EventArgs e) { object[] arr = Cells.Select(c => (object)c.Selected).ToArray(); SetArray($"Running.CellIndex", PropertyValueTypes.PropValType_Boolean, arr); } private void ManualDebug_Loaded(object sender, RoutedEventArgs e) { StartTcpServer(); Task.Run(() => { System.Threading.Thread.Sleep(500); Dispatcher.BeginInvoke(() => { InitWrapper(); StartSeq(); mask.Visibility = Visibility.Collapsed; }); }); } /// <summary> /// 启动Tcp服务器 /// </summary> [RelayCommand] private void StartTcpServer() { var serverConfig = new ServerConfig() { MaxRequestLength = 1024 * 1024, Port = 7777 }; try { if (tcpServer == null) { tcpServer = new TcpServer(); tcpServer.NewRequestReceived += TcpServer_NewRequestReceived; if (!tcpServer.Setup(serverConfig)) { ChangeTcpServerStatus("ERROR", this.lang("Tr.TcpServer.SettingFailed")); return; } if (!tcpServer.Start()) { ChangeTcpServerStatus("ERROR", this.lang("Tr.TcpServer.StartFailed")); return; } ChangeTcpServerStatus("RUNNING", this.lang("Tr.TcpServer.Running")); } else if (tcpServer.State != SuperSocket.SocketBase.ServerState.Running) { if (!tcpServer.Setup(serverConfig)) { ChangeTcpServerStatus("ERROR", this.lang("Tr.TcpServer.SettingFailed")); return; } if (!tcpServer.Start()) { ChangeTcpServerStatus("ERROR", this.lang("Tr.TcpServer.StartFailed")); return; } ChangeTcpServerStatus("RUNNING", this.lang("Tr.TcpServer.Running")); } } catch (Exception ex) { ChangeTcpServerStatus("ERROR", $"{ex.Message}"); tcpServer?.Stop(); tcpServer = null; } } /// <summary> /// 更新Tcp服务器状态 /// </summary> /// <param name="status"></param> /// <param name="info"></param> private void ChangeTcpServerStatus(string status, string info) { Dispatcher.Invoke(() => { TcpServerStatus = status; TcpServerInfo = info; }); } private void TcpServer_NewRequestReceived(TcpSession session, SuperSocket.SocketBase.Protocol.StringRequestInfo requestInfo) { string msg = requestInfo.Body; string[] datas_10015 = msg.Split(';'); //int cellIndex = int.Parse(datas_10015[1]); string strs = datas_10015[2]; string[] arr = strs.Split(','); Dispatcher.Invoke(() => { AddTestData(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]); }); } public void RefreshButtons(List<BtnConfig> settings) { if (settings == null) return; for (int i = 0; i < settings.Count; i++) { var setting = settings[i]; var margin = new Thickness(0, 0, 20, 0); if (i == settings.Count - 1) { margin = new Thickness(0); } var btn = new StatusBtn { Title = setting.Title, Tag = setting, Margin = margin }; btn.BtnClick += Btn_BtnClick; btnCache[setting.Name] = btn; btnPanel.Children.Add(btn); } } public void StartSeq() { try { executionWrapper?.StartSequence(seqPath, modelPath); } catch (Exception ex) { AppendLog(LogLevel.Error, $"启动测试序列失败 {ex.Message} {ex.StackTrace}"); } } private void InitWrapper() { try { var wrapper = new TeststandWrapper(); var AxApplicationMgr = wrapper.AxApplicationMgr; ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).BeginInit(); host.Child = AxApplicationMgr; ((System.ComponentModel.ISupportInitialize)(AxApplicationMgr)).EndInit(); wrapper.Init(); executionWrapper = wrapper; wrapper.UIMessageEvent += Wrapper_UIMessageEvent; } catch (Exception ex) { AppendLog(LogLevel.Error, $"初始化Teststand {ex.Message} {ex.StackTrace}"); } } private void SetArray(string name, PropertyValueTypes type, object[] arr) { try { var context = ((TeststandWrapper)executionWrapper).context; context.FileGlobals.DeleteSubProperty(name, 2); context.FileGlobals.NewSubProperty(name, type, true, null, 1); context.FileGlobals.GetPropertyObject(name, 0).SetNumElements(arr.Length); for (int i = 0; i < arr.Length; i++) { if (type == PropertyValueTypes.PropValType_Boolean) { context.FileGlobals.SetValBoolean($"{name}[{i}]", 0, arr[i] == null ? false : (bool)arr[i]); } else { context.FileGlobals.SetValString($"{name}[{i}]", 0, arr[i]?.ToString()); } // (type == PropertyValueTypes.PropValType_String) } } catch (Exception ex) { AppendLog(LogLevel.Error, $"写数组 {name} 错误: {ex.Message} {ex.StackTrace}"); } } private void Wrapper_UIMessageEvent(object sender, UIMessageEvent e) { try { if (e.EventCode == 10000) { executionWrapper?.SetContext(e.Data); string key = $"Running.OvenName"; executionWrapper?.SetFileGlobalValue(key, 1, OvenName); key = $"Running.OvenIndex"; executionWrapper?.SetFileGlobalValue(key, 1, OvenIndex); //key = $"Running.CellIndex"; //executionWrapper?.SetFileGlobalValue(key, 1, CellIndex); if (CellIndex >= 0) { key = $"Running.CellIndex"; object[] arr = new object[CellCount]; arr[CellIndex] = true; SetArray(key, PropertyValueTypes.PropValType_Boolean, arr); key = $"Running.CellName"; string[] names = new string[CellCount]; names[CellIndex] = CellName; SetArray(key, PropertyValueTypes.PropValType_String, names); } else { string[] names = Cells.Select(c => c.Title).ToArray(); SetArray($"Running.CellName", PropertyValueTypes.PropValType_String, names); } Dispatcher.Invoke(() => { CellGrid.IsEnabled = true; AppendLog(LogLevel.Debug, "Context初始化完成"); }); return; } if (e.EventCode == 10001) { string[] arr = e.StrData.Split(','); Dispatcher.BeginInvoke(() => { AddTestData(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]); }); return; } if (e.EventCode == 10002) { string[] arr = e.StrData.Split(','); LogLevel level = (LogLevel)int.Parse(arr[0]); Dispatcher.BeginInvoke(() => { AppendLog(level, arr[1]); }); return; } if (e.EventCode == 10003) { string[] arr = e.StrData.Split(','); DebugStatus status = (DebugStatus)int.Parse(arr[1]); Dispatcher.BeginInvoke(() => { SetStatus(arr[0], status); }); return; } if (e.EventCode == 10004) { int index = Convert.ToInt32(e.NumberData); //CellStatus status = (CellStatus)Enum.Parse(typeof(CellStatus), e.StrData); CellStatus status = (CellStatus)int.Parse(e.StrData); Dispatcher.BeginInvoke(() => { if (index < StatusCells.Count) { StatusCells[index].SetCurrentValue(StatusCell.StatusProperty, status); } }); return; } } catch (Exception ex) { AppendLog(LogLevel.Error, $"处理UI信息失败 {ex.Message} {ex.StackTrace}"); } } private void Btn_BtnClick(object sender, RoutedEventArgs e) { var btn = (StatusBtn)sender; BtnConfig config = (BtnConfig)btn.Tag; StartSingleTest(config.Name); } private void StartSingleTest(string name) { try { string key = $"Running.ActionName"; executionWrapper?.SetFileGlobalValue(key, 1, name); } catch (Exception ex) { AppendLog(LogLevel.Error, $"启动功能失败 {ex.Message} {ex.StackTrace}"); } } // 设置状态显示 private void SetStatus(string labelName, DebugStatus status) { if (btnCache.ContainsKey(labelName)) { var btn = btnCache[labelName]; btn.Status = status; } } // 重置状态显示 private void ResetStatus(string labelName) { SetStatus(labelName, DebugStatus.Idle); } // 设置测试中状态并禁用按钮 private void SetTestingStatus(string labelName, Button button) { SetStatus(labelName, DebugStatus.Testing); button.IsEnabled = false; } private void OnClearClick(object sender, RoutedEventArgs e) { TestData.Clear(); } private void OnClearLogClick(object sender, RoutedEventArgs e) { LogRichTextBox.Document.Blocks.Clear(); } private void AddTestData(string name, string send, string receive, string unit, string upper, string lower, string result, string time) { TestData.Add(new TestDataItem { Name = name, Send = send, Receive = receive, Unit = unit, UpperLimit = upper, LowerLimit = lower, Result = result, Time = time }); if (DataGridComm.Items.Count > 0) { DataGridComm.ScrollIntoView(DataGridComm.Items[DataGridComm.Items.Count - 1]); } } // 获取日志级别对应的颜色 private Brush GetLogLevelBrush(LogLevel level) { switch (level) { case LogLevel.Debug: return _debugBrush; case LogLevel.Info: return _infoBrush; case LogLevel.Warn: return _warnBrush; case LogLevel.Error: return _errorBrush; default: return _infoBrush; } } // 添加带级别的日志 private void AppendLog(LogLevel level, string message) { Dispatcher.BeginInvoke(() => { string timestamp = DateTime.Now.ToString("HH:mm:ss.fff"); string levelStr = level.ToString().ToUpper(); Paragraph? paragraph = LogRichTextBox.Document.Blocks.LastBlock as Paragraph; if (paragraph == null) { paragraph = new Paragraph(); LogRichTextBox.Document.Blocks.Add(paragraph); } // 时间戳(灰色) Run timestampRun = new Run("[" + timestamp + "] ") { Foreground = _debugBrush }; paragraph.Inlines.Add(timestampRun); // 级别标签 Brush levelBrush = GetLogLevelBrush(level); Run levelRun = new Run("[" + levelStr + "] ") { Foreground = levelBrush, FontWeight = FontWeights.SemiBold }; paragraph.Inlines.Add(levelRun); // 消息内容 Run messageRun = new Run(message + "\n") { Foreground = levelBrush }; paragraph.Inlines.Add(messageRun); LogRichTextBox.ScrollToEnd(); }); } // 兼容旧调用方式,默认 Info 级别 private void AppendLog(string message) { AppendLog(LogLevel.Info, message); } public void Stop() { try { executionWrapper?.SetFileGlobalValue("Running.StopTest", 1, true); executionWrapper?.WaitForExit(); tcpServer?.Stop(); } catch (Exception ex) { } } } public class TestDataItem : INotifyPropertyChanged { private string _name = ""; private string _receive = ""; private string _send = ""; private string _unit = ""; private string _upperLimit = ""; private string _lowerLimit = ""; private string _result = ""; private string _time = ""; public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } } public string Receive { get { return _receive; } set { _receive = value; OnPropertyChanged("Receive"); } } public string Send { get { return _send; } set { _send = value; OnPropertyChanged("Send"); } } public string Unit { get { return _unit; } set { _unit = value; OnPropertyChanged("Unit"); } } public string UpperLimit { get { return _upperLimit; } set { _upperLimit = value; OnPropertyChanged("UpperLimit"); } } public string LowerLimit { get { return _lowerLimit; } set { _lowerLimit = value; OnPropertyChanged("LowerLimit"); } } public string Result { get { return _result; } set { _result = value; OnPropertyChanged("Result"); } } public string Time { get { return _time; } set { _time = value; OnPropertyChanged("Time"); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } Plugin.BurnIn/ManualDebug/ManualDebugStyle.xaml
New file @@ -0,0 +1,130 @@ <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- 颜色定义 --> <SolidColorBrush x:Key="TsBgBrush" Color="#F0F2F5"/> <SolidColorBrush x:Key="TsPanelBrush" Color="#FFFFFF"/> <SolidColorBrush x:Key="BorderBrush" Color="#A0AEC0"/> <SolidColorBrush x:Key="PrimaryBrush" Color="#2E5C8A"/> <!-- 状态颜色画刷 --> <SolidColorBrush x:Key="StatusOKBrush" Color="#2D8659"/> <SolidColorBrush x:Key="StatusNGBrush" Color="#C53030"/> <SolidColorBrush x:Key="StatusTestingBrush" Color="#3182CE"/> <SolidColorBrush x:Key="StatusDefaultBrush" Color="#E0E0E0"/> <SolidColorBrush x:Key="BorderDarkBrush" Color="#718096"/> <!-- ActionButtonStyle 按钮样式 --> <Style x:Key="ActionButtonStyle" TargetType="Button"> <Setter Property="Height" Value="22"/> <Setter Property="Padding" Value="8,0"/> <Setter Property="Background" Value="White"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="FontSize" Value="11"/> <Setter Property="Cursor" Value="Hand"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" Padding="{TemplateBinding Padding}"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#F0F0F0"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- ManualDebug 窗口专用按钮样式 --> <Style x:Key="DebugButtonStyle" TargetType="Button"> <Setter Property="Width" Value="100"/> <Setter Property="Height" Value="32"/> <Setter Property="Background" Value="White"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="FontSize" Value="11"/> <Setter Property="Cursor" Value="Hand"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" Padding="{TemplateBinding Padding}"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#E8E8E8"/> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter Property="Background" Value="#D0D0D0"/> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Background" Value="LightGray"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- DataGrid样式 --> <Style TargetType="DataGrid"> <Setter Property="AutoGenerateColumns" Value="False"/> <Setter Property="CanUserAddRows" Value="False"/> <Setter Property="CanUserDeleteRows" Value="False"/> <Setter Property="HeadersVisibility" Value="Column"/> <Setter Property="GridLinesVisibility" Value="All"/> <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="VerticalGridLinesBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderBrush" Value="{StaticResource BorderDarkBrush}"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Background" Value="White"/> <Setter Property="RowBackground" Value="White"/> <Setter Property="AlternatingRowBackground" Value="#F5F5F5"/> <Setter Property="FontSize" Value="11"/> </Style> <Style TargetType="DataGridColumnHeader"> <Setter Property="Background" Value="#F5F5F5"/> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0,0,1,1"/> <Setter Property="Padding" Value="4"/> <Setter Property="Height" Value="26"/> <Setter Property="FontWeight" Value="Normal"/> </Style> <Style TargetType="DataGridCell"> <Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Padding" Value="2,4"/> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#BBDEFB"/> <Setter Property="Foreground" Value="Black"/> </Trigger> </Style.Triggers> </Style> <Style TargetType="DataGridRow"> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#BBDEFB"/> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#E3F2FD"/> </Trigger> </Style.Triggers> </Style> </ResourceDictionary> Plugin.BurnIn/ManualDebug/ManualDebugWindow.xaml
File was renamed from Plugin.BurnIn/ManualDebugWindow.xaml @@ -4,16 +4,18 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:sb="clr-namespace:Util.SB;assembly=Util.ManualDebug" Title="ManualDebugWindow" xmlns:pu="https://opensource.panuon.com/wpf-ui" xmlns:local="clr-namespace:Plugin.BurnIn" Style="{StaticResource ModalWindow}" Closing="Window_Closing" WindowState="Maximized" WindowStartupLocation="CenterScreen" pu:WindowXModalDialog.Buttons="{x:Null}" Height="1000" Width="900"> <Grid x:Name="sb"> <sb:ManualDebug OvenName="{Binding OvenName,Mode=OneWay}" <local:ManualDebug OvenName="{Binding OvenName,Mode=OneWay}" CellCount="{Binding CellCount,Mode=OneWay}" CellName="{Binding CellName,Mode=OneWay}" OvenIndex="{Binding OvenIndex,Mode=OneWay}" CellIndex="{Binding CellIndex,Mode=OneWay}"/> Plugin.BurnIn/ManualDebug/ManualDebugWindow.xaml.cs
File was renamed from Plugin.BurnIn/ManualDebugWindow.xaml.cs @@ -3,7 +3,6 @@ using System.ComponentModel; using System.IO; using System.Windows; using Util.SB; namespace Plugin.BurnIn { @@ -15,15 +14,26 @@ private ManualDebug debug; public ManualDebugWindow(string seqPath, string modelPath) public ManualDebugWindow(string seqPath, string modelPath, bool isMuilt) : this(seqPath, modelPath, isMuilt, null, 1) { } public ManualDebugWindow(string seqPath, string modelPath, bool isMuilt, SingleCell[] cells, int col) { DataContext = this; InitializeComponent(); debug = (ManualDebug)sb.Children[0]; ReadBtns(); if (!isMuilt) { debug.HideCells(true); } //List<BtnConfig> settings = new List<BtnConfig> { new BtnConfig { Title = "上电激活", Name = "Active" } }; debug.seqPath = seqPath; debug.modelPath = modelPath; debug.CellGrid.Columns = col; debug.CellResultGrid.Columns = col; debug.RefreshGrid(cells); } private string ovenName; @@ -56,7 +66,7 @@ } } private int cellIndex; private int cellIndex = -1; public int CellIndex { get => cellIndex; @@ -66,6 +76,16 @@ } } private int cellCount = 0; public int CellCount { get => cellCount; set { Set(ref cellCount, value); } } private void ReadBtns() { string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.ini"); Plugin.BurnIn/ManualDebug/StatusBtn.xaml
New file @@ -0,0 +1,75 @@ <UserControl x:Class="Plugin.BurnIn.StatusBtn" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Plugin.BurnIn" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Plugin.BurnIn;component/ManualDebug/ManualDebugStyle.xaml"/> </ResourceDictionary.MergedDictionaries> <Style x:Key="StatusTextStyle" TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="FontWeight" Value="SemiBold"/> <Setter Property="FontSize" Value="12"/> <Setter Property="Text" Value="-"/> <Style.Triggers> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.NG}"> <Setter Property="Text" Value="NG"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.OK}"> <Setter Property="Text" Value="OK"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.Testing}"> <Setter Property="Text" Value="TESTING"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> </Style.Triggers> </Style> <!-- 状态边框样式 --> <Style x:Key="StatusBorderStyle" TargetType="Border"> <Setter Property="Background" Value="{StaticResource StatusDefaultBrush}"/> <Setter Property="CornerRadius" Value="2"/> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="Width" Value="100"/> <Setter Property="Height" Value="24"/> <Setter Property="Margin" Value="0,5,0,0"/> <Style.Triggers> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.NG}"> <Setter Property="Background" Value="{StaticResource StatusNGBrush}"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.OK}"> <Setter Property="Background" Value="{StaticResource StatusOKBrush}"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.Testing}"> <Setter Property="Background" Value="{StaticResource StatusTestingBrush}"/> </DataTrigger> </Style.Triggers> </Style> <Style x:Key="btnStyle" TargetType="Button" BasedOn="{StaticResource DebugButtonStyle}"> <Style.Triggers> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:DebugStatus.Testing}"> <Setter Property="IsEnabled" Value="False"/> </DataTrigger> </Style.Triggers> </Style> </ResourceDictionary> </UserControl.Resources> <StackPanel> <Button x:Name="btn" Content="{Binding Title}" Style="{StaticResource btnStyle}" Click="Button_Click"/> <Border Style="{StaticResource StatusBorderStyle}"> <TextBlock Style="{StaticResource StatusTextStyle}"/> </Border> </StackPanel> </UserControl> Plugin.BurnIn/ManualDebug/StatusBtn.xaml.cs
New file @@ -0,0 +1,40 @@ using CommunityToolkit.Mvvm.ComponentModel; using System.Windows; using System.Windows.Controls; namespace Plugin.BurnIn { // 状态枚举 public enum DebugStatus { Idle = 0, // 空闲 Testing = 1, // 测试中 OK = 2, // 通过 NG = 3 // 失败 } /// <summary> /// StatusBtn.xaml 的交互逻辑 /// </summary> [ObservableObject] public partial class StatusBtn : UserControl { public event RoutedEventHandler BtnClick; public StatusBtn() { DataContext = this; InitializeComponent(); } [ObservableProperty] private string title = string.Empty; [ObservableProperty] private DebugStatus status = DebugStatus.Idle; private void Button_Click(object sender, RoutedEventArgs e) { BtnClick?.Invoke(this, e); } } } Plugin.BurnIn/ManualDebug/StatusCell.xaml
New file @@ -0,0 +1,39 @@ <UserControl x:Class="Plugin.BurnIn.StatusCell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Plugin.BurnIn" xmlns:pu="https://opensource.panuon.com/wpf-ui" mc:Ignorable="d" Padding="5" MaxHeight="80" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Style> <Style TargetType="UserControl"> <Style.Triggers> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:CellStatus.Closed}"> <Setter Property="Background" Value="Gray"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:CellStatus.OK}"> <Setter Property="Background" Value="#2D8659"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:CellStatus.NG}"> <Setter Property="Background" Value="#C53030"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> <DataTrigger Binding="{Binding Status}" Value="{x:Static local:CellStatus.Testing}"> <Setter Property="Background" Value="#3182CE"/> <Setter Property="Foreground" Value="#FFF"/> </DataTrigger> </Style.Triggers> </Style> </UserControl.Style> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock FontSize="20" FontWeight="Bold" Text="{Binding Title}"/> <TextBlock Grid.Row="1" FontSize="18" Text="{Binding Status}"/> </Grid> </UserControl> Plugin.BurnIn/ManualDebug/StatusCell.xaml.cs
New file @@ -0,0 +1,71 @@ using CommunityToolkit.Mvvm.ComponentModel; using System.Globalization; using System.Windows; using System.Windows.Controls; using System.Windows.Data; namespace Plugin.BurnIn { public enum CellStatus { Testing = 0, OK = 1, NG = 2, Closed = 99, Open = 100, Waiting = 101 } public class CellStatusConverter : IValueConverter { public static CellStatusConverter Instance = new CellStatusConverter(); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is bool b) { return b ? CellStatus.Open : CellStatus.Closed; } return CellStatus.Closed; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } /// <summary> /// ManualCell.xaml 的交互逻辑 /// </summary> [ObservableObject] public partial class StatusCell : UserControl { [ObservableProperty] private string title; public static readonly DependencyProperty StatusProperty = DependencyProperty.Register( "Status", typeof(CellStatus), typeof(StatusCell), new PropertyMetadata(CellStatus.Closed)); public CellStatus Status { get => (CellStatus)GetValue(StatusProperty); set { SetValue(StatusProperty, value); } } [ObservableProperty] private int index; public StatusCell() { this.DataContext = this; InitializeComponent(); } } } Plugin.BurnIn/Plugin.BurnIn.csproj
@@ -8,6 +8,9 @@ <ImplicitUsings>enable</ImplicitUsings> <UseWPF>true</UseWPF> <Platforms>AnyCPU;x64</Platforms> <AssemblyVersion>1.0.0.2</AssemblyVersion> <FileVersion>1.0.0.2</FileVersion> <IncludeSymbols>False</IncludeSymbols> </PropertyGroup> <ItemGroup> @@ -30,7 +33,6 @@ <ProjectReference Include="..\PLCHelper\PLCHelper.csproj" /> <ProjectReference Include="..\Plugin.TsSupport\Plugin.TsSupport.csproj" /> <ProjectReference Include="..\SimpleUtil\HMI.LogUtil\HMI.LogUtil.csproj" /> <ProjectReference Include="..\Util.ManualDebug\Util.ManualDebug.csproj" /> </ItemGroup> <ItemGroup> @@ -62,6 +64,12 @@ </ItemGroup> <ItemGroup> <Compile Update="ManualDebug\StatusCell.xaml.cs"> <SubType>Code</SubType> </Compile> <Compile Update="ManualDebug\StatusBtn.xaml.cs"> <SubType>Code</SubType> </Compile> <Compile Update="TestResultView.xaml.cs"> <SubType>Code</SubType> </Compile> Plugin.BurnIn/Scanner.xaml.cs
@@ -390,7 +390,7 @@ try { targetCellInfo = null; serialPort.Dispose(); serialPort?.Dispose(); serialPort = null; } catch (Exception ex) Plugin.BurnIn/SingleCell.xaml.cs
@@ -521,16 +521,21 @@ //waterChart?.AddData("水箱温度", temp); //waterChart?.AddData("回水温度", backTemp); //waterChart?.AddData("流量", pressure); var time = DateTime.Now; charts[0].AddData("水箱温度", time, temp); charts[0].AddData("回水温度", time, backTemp); charts[0].AddData("流量", time, pressure); } public void AddElectricData(double data) { charts[1].AddData("电流", DateTime.Now, data); //electricChart.AddData("", data); } public void AddVData(double data) { //vChart.AddData("", data); charts[2].AddData("电压", DateTime.Now, data); } public void ClearChart() @@ -1059,15 +1064,16 @@ return; } string modelPath = table.parent.testModelFile; int dutNo = table.index * table.cellCount + this.index; var win = new ManualDebugWindow(manualDebugSeq, modelPath) var win = new ManualDebugWindow(manualDebugSeq, modelPath, false) { Title = $"{this.title}手动调试", Owner = Window.GetWindow(this), OvenIndex = this.table.index, OvenName = this.table.title, CellCount = this.table.cells.Length, CellIndex = dutNo, CellIndex = this.index, CellName = this.title }; win.ShowDialog(); Plugin.BurnIn/TestResultView.xaml.cs
@@ -245,7 +245,7 @@ { foreach (var oven in tables) { executionWrapper?.SetStationGlobalValue<string>($"StationHMI.UUTHMI[{oven.index}].Name", 1, oven.Name); executionWrapper?.SetStationGlobalValue<string>($"StationHMI.UUTHMI[{oven.index}].Name", 1, oven.title); } executionWrapper?.CommitToDisk(false); } @@ -271,7 +271,7 @@ { try { executionWrapper?.SetStationGlobalValue<bool>("StationState.StopTest", 0, true, true); executionWrapper?.SetStationGlobalValue<bool>("StationHMI.AllStop", 0, true, true); try { @@ -453,6 +453,7 @@ tables[ovenIndex].ClearChartData(); return; } if (MethodCode == 11) { /// 清除穴位参数 Plugin.TestResult/DataTable.xaml.cs
@@ -607,17 +607,18 @@ { infoTable.UpdateNumber(infoTable.okCount + ok, infoTable.ngCount + ng); if (ParamSetting.ProbeByModel) { //if (ParamSetting.ProbeByModel) //{ } else { //} //else //{ //} IniFileHelper.WriteIniData($"Oven_{index}", "Pass", infoTable.okCount.ToString(), this.CountIniPath); IniFileHelper.WriteIniData($"Oven_{index}", "Fail", infoTable.ngCount.ToString(), this.CountIniPath); } } /// <summary> Plugin.TsExecution/SingleControl.xaml
@@ -455,7 +455,13 @@ VerticalContentAlignment="Center" Content="{DynamicResource Ts.ProbeCount}"/> <Label Padding="0" FontSize="12" Margin="0,0,15,0" VerticalAlignment="Center" VerticalContentAlignment="Center" Content="{Binding ProbeCount}"/> VerticalContentAlignment="Center"> <TextBlock> <Run Text="{Binding ProbeCount}"/> <Run Text="/"/> <Run Text="{Binding ProbeWarn,Mode=OneWay}"/> </TextBlock> </Label> <StackPanel x:Name="probeWarnPanel" Orientation="Horizontal" Visibility="Collapsed"> <Label x:Name="alarmLabel" Padding="0" FontSize="12" @@ -463,7 +469,7 @@ VerticalContentAlignment="Center" Content="{DynamicResource Ts.ProbeAlarmCount}"/> <Label x:Name="alarmValue" Padding="0" FontSize="12" VerticalAlignment="Center" VerticalContentAlignment="Center" Content="{Binding ProbeWarn}"/> VerticalContentAlignment="Center" Content="{Binding ProbeWarn,Mode=OneWay}"/> </StackPanel> <Button FontSize="12" Style="{StaticResource LinkButton}" Plugin.TsExecution/SingleControl.xaml.cs
@@ -5,6 +5,7 @@ using HMI.Util; using NationalInstruments.TestStand.Interop.API; using NPOI.HSSF.UserModel; using NPOI.SS.Formula.Functions; using NPOI.SS.UserModel; using Plugin.TsExecution.Entity; using System; @@ -180,6 +181,16 @@ set { Set(ref _probeCount, value); try { if (ProbeWarn <= 0) probeCountAlarm.Visibility = Visibility.Collapsed; else if (value >= ProbeWarn) probeCountAlarm.Visibility = Visibility.Visible; else probeCountAlarm.Visibility = Visibility.Collapsed; } catch { } } } @@ -222,7 +233,15 @@ } } public int ProbeWarn { get; private set; } private int _probeWarn; public int ProbeWarn { get => _probeWarn; private set { Set(ref _probeWarn, value); } } private bool isAutoMode; public bool IsAutoMode @@ -246,9 +265,9 @@ Interval = 100 }; refreshTimer.Elapsed += RefreshTimer_Elapsed; RefreshProbeCount(null); ReadCounter(); InitializeComponent(); RefreshProbeCount(null); try { var value = ParameterManager.GetCommonParameterByName("AutoTestMode"); @@ -653,10 +672,6 @@ /// 写到配置文件 IniFileHelper.WriteIniData("Socket" + this.index.ToString(), "ProbeCount", count.ToString(), this.CountIniPath); ProbeCount = count; //if (ProbeWarn <= 0) probeCountAlarm.Visibility = Visibility.Collapsed; //else if (count >= ProbeWarn) probeCountAlarm.Visibility = Visibility.Visible; //else probeCountAlarm.Visibility = Visibility.Collapsed; } public void RefreshProduct(ProductData product) SimpleUtil/HMI.Simple.Util/DataSender.cs
New file @@ -0,0 +1,103 @@ using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace HMI.Simple.Util { public class DataSender { private string _ip; private int _port; private bool _isConnected = false; // 是否连接 private Socket _clientSocket; // 套接字 private Thread _receiveThread = null; // 接收线程 private volatile bool needRecieve = true; public event EventHandler<string> ExecuteMessageChanged; public DataSender(string ip, int port) { this._ip = ip; this._port = port; } public void Connect() { try { _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ipaddress = IPAddress.Parse(this._ip); IPEndPoint endpoint = new IPEndPoint(ipaddress, _port); _clientSocket.Connect(endpoint); _isConnected = true; _receiveThread = new Thread(Received); _receiveThread.IsBackground = true; _receiveThread.Start(); } catch (Exception ex) { needRecieve = false; _receiveThread?.Abort(); _receiveThread = null; _clientSocket.Close(); _isConnected = false; throw ex; } } public void Disconnect() { needRecieve = false; _clientSocket.Close(); _receiveThread?.Abort(); _receiveThread = null; _isConnected = false; } private void Send(string data) { byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(data); _clientSocket.Send(arrClientSendMsg); } private void Received() { //while (needRecieve) //{ // byte[] arrRecMsg = new byte[1024 * 1024]; // int length = _clientSocket.Receive(arrRecMsg); // string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length); // ExecuteMessageChanged?.Invoke(this, strRecMsg); // Thread.Sleep(100); //} } public bool SendStep(int ovenIndex, int cellIndex, string name, string send, string value, string unit, string upper, string lower, string result, string time, out string errorMsg) { errorMsg = null; try { if (!_isConnected) { errorMsg = "Not Connected"; return false; } string msg = $"{ovenIndex};{cellIndex};{name},{send},{value},{unit},{upper},{lower},{result},{time}\n"; Send(msg); return true; } catch (Exception ex) { errorMsg = ex.Message; return false; } } } } SimpleUtil/HMI.Simple.Util/HMI.Simple.Util.csproj
@@ -95,6 +95,7 @@ <Compile Include="ProductUtil.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="SqliteHelper.cs" /> <Compile Include="DataSender.cs" /> <Compile Include="XmlHelper.cs" /> </ItemGroup> <ItemGroup>