|
using System;
|
using System.Runtime.InteropServices;
|
using System.Windows;
|
using System.Windows.Controls;
|
using System.Windows.Media;
|
using System.Windows.Threading;
|
using static SmartScanner.IDViewerDefines;
|
using static SmartScanner.IDViewerSDK;
|
using static SmartScanner.IDViewerSDK2;
|
using System.Drawing;
|
using System.Drawing.Imaging;
|
using System.Windows.Media.Imaging;
|
using System.IO;
|
using System.Runtime;
|
using OpenCvSharp;
|
using System.Windows.Media.Media3D;
|
using System.Collections.Generic;
|
using System.Threading;
|
using System.Net.Sockets;
|
using System.Text;
|
using static System.Net.Mime.MediaTypeNames;
|
using System.Net;
|
using System.Threading.Tasks;
|
using static OpenCvSharp.XImgProc.CvXImgProc;
|
using System.Diagnostics;
|
using System.Linq;
|
using System.Text.RegularExpressions;
|
using Newtonsoft.Json;
|
using SmartScanner.ViewModel;
|
using SmartScanner.OperateLog;
|
using System.Windows.Input;
|
using System.Timers;
|
using System.Net.NetworkInformation;
|
|
namespace SmartScanner
|
{
|
/// <summary>
|
/// MainWindow.xaml 的交互逻辑
|
/// </summary>
|
///
|
public partial class MainWindow : System.Windows.Window
|
{
|
//设备的句柄
|
private readonly Dictionary<int, IntPtr> _deviceHandles = new Dictionary<int, IntPtr>();
|
|
//图像句柄
|
private readonly Dictionary<int, IntPtr> _imagePtr = new Dictionary<int, IntPtr>();
|
|
//模型匹配
|
private readonly Dictionary<int, IntPtr> _DetectorSelect = new Dictionary<int, IntPtr>();
|
|
//选择的设备
|
public int selectedIndex;
|
|
//设备编号
|
public int[] deviceIndex = new int[100];
|
|
//连接设备个数
|
int IsConnected = 0;
|
|
public IntPtr devicesListHandle;
|
|
//耗时计算
|
Stopwatch stopwatch = new Stopwatch();
|
|
ModbusTCPClient modbusTCPClient = new ModbusTCPClient();
|
|
//实例化log类
|
//EnhancedLogViewModel EnhancedLogViewModel.Instance = new EnhancedLogViewModel();
|
|
//设备信息结构体句柄
|
IDDeviceInfo[] deviceInfo = new IDDeviceInfo[100];
|
|
delegate void IDViewerCallBack(IntPtr device, IntPtr image);
|
delegate void IDViewerCallBack1(IntPtr device, IntPtr image);
|
|
//检测连接状态定时器
|
private System.Threading.Timer deviceStatusTimer;
|
private int deviceStatusInterval = 3000; // 3秒
|
|
//回调委托
|
static IDViewerCallBack[] callbackDelegate;
|
|
IDNodeParam iDNodeParam;
|
|
//创建检测器
|
public IntPtr detector = new IntPtr();
|
public static string filePath = ".\\detector.txt";
|
string Detector_Device = File.ReadAllText(filePath);
|
|
//信号保持时间
|
public static string holdtime = ".\\HoldTime.txt";
|
public string Hold_Time = File.ReadAllText(holdtime);
|
|
//信号保持时间
|
public static string selflockingtime = ".\\SelflockingTime.txt";
|
public string Selflocking_Time = File.ReadAllText(holdtime);
|
//string Detector_Device = "CPU";
|
//string modelPath = ".\\model\\best.onnx";
|
|
//TCP通讯参数
|
//private TcpListener _server;
|
//private TcpClient _client;
|
//private NetworkStream _stream;
|
private TcpServerManager _tcpServerManager;
|
|
//图像字节数组
|
int batchSize = 2;
|
byte[] imgBatch1 = null;
|
byte[] imgBatch2 = null;
|
|
//输出结果数组
|
public bool[] outputs = new bool[20];
|
private TextBlock[] cameraAliasLabels;
|
private TextBlock[] deviceNames;
|
|
//NG图片路径集合
|
public List<string> Image_NG = new List<string>();
|
|
//寄存器控制变量
|
public int[] usOutput = new int[16];
|
public int[] usOutput2 = new int[4];
|
public bool USOUT = true;
|
public int[] usOutput_tcp;
|
//输出模式控制
|
bool IsSignleOutput = false;
|
|
//方案配置参数
|
public string json;
|
public ResultJudge.JudgmentConfiguration config = new ResultJudge.JudgmentConfiguration();
|
|
//ModBus心跳定时器
|
private System.Threading.Timer heartbeatTimer;
|
private int heartbeatInterval = 30000; // 30秒
|
|
//Modbus重连参数
|
private int _reconnectAttempts = 0;//重连尝试次数
|
private const int MAX_RECONNECT_ATTEMPTS = 5; //最大重连尝试次数
|
private bool _isReconnecting = false;//是否正在重连
|
private System.Threading.Timer _reconnectTimer;//重连定时器
|
private const int RECONNECT_INTERVAL = 2000; // 重连间隔时间(毫秒)
|
private string _lastIpAddress = ""; // 最后连接的IP地址
|
private int _lastPort = 502; // 最后连接的端口
|
|
//结果信号定时器
|
private System.Timers.Timer OutputTimer;
|
|
//定期删除图像
|
private ImageCleanupService _cleanupService;
|
|
public MainWindow()
|
{
|
if (!LBProtect.ValidateFingerprint())
|
{
|
MessageBox.Show("软件未授权在此硬件上运行!");
|
Close();
|
return;
|
}
|
InitializeComponent();
|
DataContext = EnhancedLogViewModel.Instance;
|
// 定期清图服务初始化
|
InitializeCleanupService();
|
|
LoadDataAsync();
|
// SDK初始化
|
InitSDK();
|
// 结果显示界面初始化
|
InitUI();
|
// 用户偏好设置初始化
|
InitUserConfig();
|
for (int i = 0; i < outputs.Length; i++)
|
{
|
outputs[i] = false;
|
}
|
// 默认加载上次检测方案
|
LoadLastUsedConfiguration(true);
|
this.Closing += MainWindow_Closing;
|
// 获取ListView中的ScrollViewer引用
|
// 获取ScrollViewer引用并传递给ViewModel
|
Loaded += (sender, e) =>
|
{
|
if (FindVisualChild<ScrollViewer>(LogListView) is ScrollViewer scrollViewer)
|
{
|
EnhancedLogViewModel.Instance.LogScrollViewer = scrollViewer;
|
}
|
};
|
this.WindowState = WindowState.Maximized;
|
Loaded += (s, e) => RefreshIpButton_Click(null, null); // 自动加载IP
|
RefreshModelList(); // 自动加载模型列表
|
RefreshDetectionPlanList(); // 自动加载检测方案列表
|
RefreshProjectList(); // 自动加载工程文件列表
|
}
|
private async void LoadDataAsync()
|
{
|
LoadingWindow loadingWindow = new LoadingWindow();
|
loadingWindow.Show();
|
await Task.Delay(2000);
|
loadingWindow.Close();
|
}
|
|
#region 初始化
|
//SDK初始化
|
private void InitSDK()
|
{
|
try
|
{
|
long result = IDVIEWER_Init_();
|
if (result != 0)
|
{
|
MessageBox.Show("SDK初始化失败,错误码:" + result);
|
}
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine(ex.Message);
|
}
|
}
|
//界面初始化
|
private void InitUI()
|
{
|
cameraAliasLabels = new TextBlock[30];
|
//deviceNames = new TextBlock[30];
|
cameraAliasLabels[0] = cameraAlias0;
|
cameraAliasLabels[1] = cameraAlias1;
|
cameraAliasLabels[2] = cameraAlias2;
|
cameraAliasLabels[3] = cameraAlias3;
|
cameraAliasLabels[4] = cameraAlias4;
|
cameraAliasLabels[5] = cameraAlias5;
|
cameraAliasLabels[6] = cameraAlias6;
|
cameraAliasLabels[7] = cameraAlias7;
|
cameraAliasLabels[8] = cameraAlias8;
|
cameraAliasLabels[9] = cameraAlias9;
|
cameraAliasLabels[10] = cameraAlias10;
|
cameraAliasLabels[11] = cameraAlias11;
|
cameraAliasLabels[12] = cameraAlias12;
|
cameraAliasLabels[13] = cameraAlias13;
|
cameraAliasLabels[14] = cameraAlias14;
|
cameraAliasLabels[15] = cameraAlias15;
|
cameraAliasLabels[16] = cameraAlias16;
|
cameraAliasLabels[17] = cameraAlias17;
|
cameraAliasLabels[18] = cameraAlias18;
|
cameraAliasLabels[19] = cameraAlias19;
|
cameraAliasLabels[20] = cameraAlias20;
|
cameraAliasLabels[21] = cameraAlias21;
|
cameraAliasLabels[22] = cameraAlias22;
|
cameraAliasLabels[23] = cameraAlias23;
|
//deviceNames[0] = deviceName0;
|
//deviceNames[1] = deviceName1;
|
//deviceNames[2] = deviceName2;
|
//deviceNames[3] = deviceName3;
|
//deviceNames[4] = deviceName4;
|
//deviceNames[5] = deviceName5;
|
//deviceNames[6] = deviceName6;
|
//deviceNames[7] = deviceName7;
|
//deviceNames[8] = deviceName8;
|
//deviceNames[9] = deviceName9;
|
//deviceNames[10] = deviceName10;
|
//deviceNames[11] = deviceName11;
|
//deviceNames[12] = deviceName12;
|
//deviceNames[13] = deviceName13;
|
//deviceNames[14] = deviceName14;
|
//deviceNames[15] = deviceName15;
|
//deviceNames[16] = deviceName16;
|
//deviceNames[17] = deviceName17;
|
//deviceNames[18] = deviceName18;
|
//deviceNames[19] = deviceName19;
|
//deviceNames[20] = deviceName20;
|
//deviceNames[21] = deviceName21;
|
//deviceNames[22] = deviceName22;
|
//deviceNames[23] = deviceName23;
|
}
|
//用户配置初始化
|
private void InitUserConfig()
|
{
|
DownloadData downloadData = new DownloadData();
|
downloadData.Init();
|
if (DownloadData.MemoryAlarm_main)
|
{
|
downloadData.CheckStorage();
|
}
|
IsSignleOutput = (bool)OutputCheckBox.IsChecked;
|
//TCP端口初始化
|
// 如果从未设置过,使用默认值
|
if (string.IsNullOrEmpty(Properties.Settings.Default.DefaultPort))
|
{
|
Properties.Settings.Default.DefaultPort = "8080";
|
Properties.Settings.Default.SelectedPort = 8080;
|
}
|
|
// 确保端口在合法范围内
|
if (Properties.Settings.Default.SelectedPort < 1 ||
|
Properties.Settings.Default.SelectedPort > 65535)
|
{
|
Properties.Settings.Default.SelectedPort = 8080;
|
}
|
|
// 尝试选中已保存的端口
|
foreach (ComboBoxItem item in TCPServer_PortComboBox.Items)
|
{
|
if (int.TryParse(item.Content.ToString(), out int port) &&
|
port == Properties.Settings.Default.SelectedPort)
|
{
|
TCPServer_PortComboBox.SelectedItem = item;
|
return;
|
}
|
}
|
|
// 如果保存的端口不在预设列表中,显示在编辑框
|
TCPServer_PortComboBox.Text = Properties.Settings.Default.SelectedPort.ToString();
|
}
|
//定期清图服务初始化
|
private void InitializeCleanupService()
|
{
|
// 从设置中获取参数
|
string imageDir = Properties.Settings.Default.DataSavingRoad;
|
int retentionDays = Properties.Settings.Default.DeleteImageDays;
|
bool isEnabled = Properties.Settings.Default.ImageDeleteEnabled;
|
|
if (isEnabled && !string.IsNullOrWhiteSpace(imageDir))
|
{
|
_cleanupService = new ImageCleanupService(imageDir, retentionDays);
|
_cleanupService.Start();
|
}
|
}
|
protected override void OnClosed(EventArgs e)
|
{
|
_cleanupService?.Stop();
|
ExcelResultRecorder.FlushRecords();
|
base.OnClosed(e);
|
}
|
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
{
|
DownloadData.isOP = false; // 窗口关闭时执行操作
|
// 可选:取消关闭(通过 e.Cancel = true)
|
deviceStatusTimer?.Dispose();
|
deviceStatusTimer = null;
|
|
// 清理Modbus相关定时器
|
heartbeatTimer?.Dispose();
|
heartbeatTimer = null;
|
_reconnectTimer?.Dispose();
|
_reconnectTimer = null;
|
|
// 停止日志自动保存服务
|
EnhancedLogViewModel.Instance?.StopAutoSaveService();
|
|
DisposeDetector_CPU(detector);
|
if (devicesListHandle != IntPtr.Zero)
|
{
|
long result = IDVIEWER_UnInit_(devicesListHandle);
|
}
|
//TCP端口配置
|
// 验证当前端口值
|
if (int.TryParse(TCPServer_PortComboBox.Text, out int port) &&
|
port >= 1 && port <= 65535)
|
{
|
Properties.Settings.Default.SelectedPort = port;
|
Properties.Settings.Default.DefaultPort = port.ToString();
|
}
|
else
|
{
|
// 恢复为默认值
|
Properties.Settings.Default.SelectedPort = 8080;
|
Properties.Settings.Default.DefaultPort = "8080";
|
}
|
|
Properties.Settings.Default.Save();
|
foreach (System.Windows.Window window in System.Windows.Application.Current.Windows.OfType<DownloadData>().ToList())
|
{
|
window.Close();
|
}
|
Process.GetCurrentProcess().Kill();
|
}
|
// 当设置变更时重新初始化服务
|
private void OnSettingsChanged(object sender, EventArgs e)
|
{
|
_cleanupService?.Stop();
|
InitializeCleanupService();
|
}
|
// 辅助方法:查找视觉树中的子元素
|
private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
|
{
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
{
|
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
if (child is T result)
|
return result;
|
|
var childResult = FindVisualChild<T>(child);
|
if (childResult != null)
|
return childResult;
|
}
|
return null;
|
}
|
|
#endregion
|
#region 设备刷新与连接
|
private async void Refresh_Btn_Click(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
Refresh_Btn.IsEnabled = false;
|
IsConnected = 0;
|
// 加载相机连接顺序映射表
|
var productManager = new ProductManager();
|
var mapping = productManager.LoadConfig();
|
bool Bl = true;
|
|
if (mapping.Count == 0)
|
{
|
MessageBox.Show("映射表为空,请先配置顺序和IP", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
return;
|
}
|
LoadingWindow loadingWindow = new LoadingWindow();
|
loadingWindow.Show();
|
loadingWindow.Loading.Text = "设备连接中,请稍候";
|
|
await Task.Run(() =>
|
{
|
// 刷新相机列表
|
RefreshDeviceList();
|
|
// 按照映射表顺序连接相机
|
foreach (var item in mapping.OrderBy(x => x.Key))
|
{
|
int sequence = item.Key;
|
string ip = item.Value;
|
ConnectDeviceByIP(sequence, ip);
|
}
|
Bl = false;
|
});
|
await Task.Run(() =>
|
{
|
while (true)
|
{
|
if (!Bl)
|
{
|
this.Dispatcher.Invoke(new Action(() =>
|
{
|
Refresh_Btn.IsEnabled = true;
|
}));
|
break;
|
}
|
}
|
});
|
|
loadingWindow.Close();
|
// 创建定时器,定时检测设备连接状态
|
deviceStatusTimer = new System.Threading.Timer(DeviceConnectbeatCallback, null, Timeout.Infinite, deviceStatusInterval);
|
// 启动定时器,立即开始并每隔MemoryAlarmInterval毫秒执行一次
|
deviceStatusTimer.Change(0, deviceStatusInterval);
|
GetMessage($"设备已全部连接完成\n连接台数:{IsConnected}");
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"请先配置相机连接顺序:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
}
|
// 刷新相机列表
|
private void RefreshDeviceList()
|
{
|
try
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DeviceListBox.Items.Clear();
|
|
}));
|
// 获取设备列表句柄
|
devicesListHandle = IDVIEWER_DiscoveryDevices_(500);
|
Console.WriteLine($"获取设备列表句柄");
|
|
// 获取设备总数
|
int deviceCount = (int)IDVIEWER_GetDevicesLength_(devicesListHandle);
|
Console.WriteLine($"获取设备总数:{deviceCount}");
|
Task.Run(() => GetMessage($"检测到 {deviceCount} 台设备"));
|
|
// 获取相机IP列表
|
for (int i = 0; i < deviceCount; i++)
|
{
|
IDViewerSDK.IDVIEWER_SelectIDDeviceInfo_(devicesListHandle, ref deviceInfo[i], (uint)i);
|
string deviceIP = deviceInfo[i].cameraIP.Trim();
|
|
// 将相机添加到界面列表
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DeviceListBox.Items.Add(deviceIP);
|
|
}));
|
|
|
}
|
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"设备检测失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
}
|
|
// 通过IP连接相机
|
private void ConnectDeviceByIP(int sequence, string ip)
|
{
|
IntPtr deviceHandle = IntPtr.Zero;
|
IntPtr imagePtr = IntPtr.Zero;
|
try
|
{
|
// 创建设备句柄
|
IDVIEWER_CreateDeviceByIP_(ip, ref deviceHandle);
|
if (deviceHandle == IntPtr.Zero)
|
{
|
MessageBox.Show($"未搜索到该设备:{ip}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
return;
|
}
|
// 打开设备
|
IDDevice_Open(deviceHandle);
|
// 读设备当前各项参数
|
double getGain = 0.0;
|
long resultGetGain_1330 = IDDevice_GetGain_1330(deviceHandle, 0, ref getGain);
|
|
IDDeviceHarewareParams iDDeviceHarewareParams;
|
iDDeviceHarewareParams = IDDevice_GetHardWareParams(deviceHandle);
|
IDNodeParam focusingLocation1 = iDDeviceHarewareParams.exposure;
|
IDNodeParam focusingLocation2 = iDDeviceHarewareParams.gamma;
|
|
float getexposure = focusingLocation1.value;
|
float getgamma = focusingLocation2.value;
|
|
Console.WriteLine($"{sequence}号设备当前曝光:{getexposure}");
|
Console.WriteLine($"{sequence}号设备当前增益:{getGain}");
|
Console.WriteLine($"{sequence}号设备当前伽马:{getgamma}");
|
Console.WriteLine($"设备{sequence}连接成功");
|
|
// 检查设备是否连接成功
|
long isConnected = IDDevice_IsConnected(deviceHandle);
|
if (isConnected != 1)
|
{
|
MessageBox.Show($"设备连接失败:{ip}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DeviceListBox.Items.Remove(ip);
|
|
}));
|
return;
|
}
|
// 初始化图像句柄
|
long result = IDImage_Init(ref imagePtr);
|
// 存储设备和图像句柄
|
_deviceHandles[sequence] = deviceHandle;
|
_imagePtr[sequence] = imagePtr;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
cameraAliasLabels[sequence - 1].Text = sequence.ToString();
|
//deviceNames[sequence - 1].Text = deviceInfo[sequence - 1].cameraAlias;
|
}));
|
IsConnected++;
|
// SDK存在BUG,相机连接后取的前几张图异常,临时解决方案
|
// 连接后取3张图丢弃
|
//for (int i = 0; i <= 3; i++)
|
//{
|
// IDDevice_CaptureImage(deviceHandle, imagePtr);
|
//}
|
Refresh_ImageParameter(deviceHandle);
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"连接设备时出错:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DeviceListBox.Items.Remove(ip);
|
|
}));
|
}
|
}
|
static List<double> gainList = new List<double>();
|
static IDDOParamsCreate iDDOParamsCreate = new IDDOParamsCreate();
|
static IDDOParams iDDOParams = iDDOParamsCreate.create();
|
static void Refresh_ImageParameter(IntPtr device)
|
{
|
/******获取增益******/
|
int count = 0;
|
long resultCount = IDDevice_GetGainCount(device, ref count);
|
double getAtGain = 0.0;
|
IDDevice_GetGain_1330(device, 0, ref getAtGain);
|
|
double Gain = 0.0;
|
for (int i = 0; i < count; i++)
|
{
|
IDDevice_SetGain(device, 0, i);
|
long ii = IDDevice_GetGain_1330(device, 0, ref Gain);
|
if (ii == 0)
|
{
|
gainList.Add(Gain);
|
}
|
}
|
|
double searchValue = getAtGain;
|
// 在 List 中查找该增益值
|
int index = gainList.IndexOf(searchValue);
|
|
if (index >= 0)
|
{
|
IDDevice_SetGain(device, 0, index);
|
}
|
|
IDDeviceHarewareParams iDDeviceHarewareParams;
|
iDDeviceHarewareParams = IDDevice_GetHardWareParams(device);
|
IDNodeParam focusingLocation = iDDeviceHarewareParams.focusingLocation;
|
IDNodeParam focusingLocation1 = iDDeviceHarewareParams.exposure;
|
IDNodeParam focusingLocation2 = iDDeviceHarewareParams.gamma;
|
|
float maxValue = focusingLocation.maxValue;
|
float CurrentValue = focusingLocation.value;
|
float getexposure = focusingLocation1.value;
|
float getgamma = focusingLocation2.value;
|
|
//添加DO到方案,只需执行一次。
|
for (int i = 0; i <= 2; i++)
|
{
|
iDDOParams.pin = (uint)i;
|
iDDOParams.status = 0;
|
iDDOParams.doModel = 0;
|
iDDOParams.durationTime = 2000;
|
iDDOParams.doSource = IDDoEventSource.EVENT_SOURCE_OFF_C;
|
long retm8 = addDOParam(device, ref iDDOParams);
|
Console.WriteLine("当前添加第" + i + "组,ret:" + retm8);
|
}
|
|
/******将获取的参数设置一次******/
|
//double getexposure1 = getexposure;
|
//double getgamma1 = getgamma;
|
//int CurrentValue1 = (int)CurrentValue;
|
|
//long g1 = IDDevice_SetExposure(device, 0, getexposure1);
|
//long g3 = IDDevice_SetGamma(device, 0, getgamma1);
|
//long g4 = IDDevice_SetFocusLocation(device, 0, CurrentValue1);
|
}
|
#endregion
|
#region 设备信息显示
|
private void DeviceListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
{
|
if (DeviceListBox.SelectedIndex != -1)
|
{
|
CameraIP.Text = deviceInfo[DeviceListBox.SelectedIndex].cameraIP.Trim();
|
CameraNetMask.Text = deviceInfo[DeviceListBox.SelectedIndex].cameraNetMask.Trim();
|
CameraGateWay.Text = deviceInfo[DeviceListBox.SelectedIndex].cameraGateWay.Trim();
|
CameraFirmwareVersion.Text = deviceInfo[DeviceListBox.SelectedIndex].cameraFirmwareVersion.Trim();
|
CameraAlias.Text = deviceInfo[DeviceListBox.SelectedIndex].cameraAlias;
|
CameraModel.Text = deviceInfo[DeviceListBox.SelectedIndex].cameraModel.Trim();
|
}
|
else { return; }
|
}
|
#endregion
|
#region 日志显示
|
//日志显示
|
private void GetMessage(string obj)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Log.AppendText(obj + Environment.NewLine);
|
Log.ScrollToEnd();
|
}));
|
}
|
//ModBus日志显示
|
private void GetMessage_Modbus(string obj)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Client_LogsTextBox.AppendText(obj + Environment.NewLine);
|
Client_LogsTextBox.ScrollToEnd();
|
}));
|
}
|
#endregion
|
//深度学习模型推理模块
|
private void Reasoning_AI(IntPtr detector, byte[] ImageBath, int Image_Width, int Image_Height, out int[] classIds, out int[] numBoxes, out float[] prob,
|
out float[] x1, out float[] y1, out float[] x2, out float[] y2, int sequence)
|
{
|
// 初始化输出参数
|
batchSize = 1;
|
x1 = new float[100];
|
y1 = new float[100];
|
x2 = new float[100];
|
y2 = new float[100];
|
prob = new float[100];
|
classIds = new int[100];
|
numBoxes = new int[batchSize];
|
|
try
|
{
|
// 检查 detector 指针是否有效
|
if (detector == IntPtr.Zero)
|
{
|
throw new ArgumentNullException(nameof(detector), "Detector pointer is null (IntPtr.Zero)");
|
}
|
// 检查 ImageBath 是否为空或大小不正确
|
if (ImageBath == null || ImageBath.Length == 0)
|
{
|
throw new ArgumentException("Image batch data is null or empty", nameof(ImageBath));
|
}
|
// 检查图像尺寸是否合理
|
if (Image_Width <= 0 || Image_Height <= 0)
|
{
|
throw new ArgumentException($"Invalid image dimensions: Width={Image_Width}, Height={Image_Height}");
|
}
|
// 检查 batchSize 是否合理
|
if (batchSize <= 0)
|
{
|
throw new InvalidOperationException($"Invalid batch size: {batchSize}");
|
}
|
// 检查输出缓冲区是否足够大
|
if (x1.Length < 100 || y1.Length < 100 || x2.Length < 100 || y2.Length < 100 || prob.Length < 100 || classIds.Length < 100)
|
{
|
throw new InvalidOperationException("Output buffer size is too small (must be at least 100)");
|
}
|
// 调用 C++ API
|
PredictDetector_CPU(
|
detector,
|
ImageBath,
|
x1, y1, x2, y2,
|
prob,
|
classIds,
|
numBoxes,
|
100,
|
Image_Width,
|
Image_Height,
|
batchSize,
|
0.25f,
|
0.3f,
|
1,
|
sequence
|
);
|
}
|
catch (SEHException ex)
|
{
|
// 记录详细的错误信息
|
Console.Error.WriteLine($"SEHException in PredictDetector_CPU: {ex.Message}");
|
Console.Error.WriteLine($"Detector: {detector}");
|
Console.Error.WriteLine($"ImageBatch Length: {ImageBath?.Length ?? 0}");
|
Console.Error.WriteLine($"Image Size: {Image_Width}x{Image_Height}");
|
Console.Error.WriteLine($"Batch Size: {batchSize}");
|
|
// 可以选择重新抛出或返回默认值
|
throw new InvalidOperationException("Failed to run AI reasoning due to native code error", ex);
|
}
|
catch (Exception ex)
|
{
|
Console.Error.WriteLine($"Error in Reasoning_AI: {ex.Message}");
|
throw;
|
}
|
}
|
|
|
// 测试方法
|
private void Start_Detector_Btn_Click(object sender, RoutedEventArgs e)
|
{
|
string images_path = "D:\\01 LBImage\\20241010\\10_59_24_2.bmp";
|
Mat mat = Cv2.ImRead(images_path);
|
int width = mat.Width;
|
int height = mat.Height;
|
int channel = mat.Channels();
|
byte[] imgBatch = new byte[width * height * channel];
|
int batchSize = 1;
|
float[] x1 = new float[1000], y1 = new float[1000], x2 = new float[1000], y2 = new float[1000];
|
float[] prob = new float[1000];
|
int[] classIds = new int[1000];
|
int[] numBoxes = new int[batchSize];
|
Marshal.Copy(mat.Data, imgBatch, 0, imgBatch.Length);
|
PredictDetector_CPU(detector, imgBatch, x1, y1, x2, y2, prob, classIds, numBoxes, 100, width, height, batchSize, 0.25f, 0.3f, 1, 1);
|
for (int i = 0; i < batchSize; i++)
|
{
|
for (int j = 0; j < numBoxes[i]; j++)
|
{
|
float x1Val = x1[j];
|
float y1Val = y1[j];
|
float x2Val = x2[j];
|
float y2Val = y2[j];
|
float probVal = prob[j];
|
int classId = classIds[j];
|
}
|
}
|
}
|
|
#region ModBus通讯设置与检测模块
|
#region 加载端口
|
private void LoadPorts()
|
{
|
//Server_PortComboBox.ItemsSource = new[] { "8000", "8001", "8002" };
|
//Client_PortComboBox.ItemsSource = new[] { "8000", "8001", "8002" };
|
Client_PortComboBox.ItemsSource = new[] { "502" };
|
}
|
#endregion
|
#region ModBus通讯模块
|
private void Client_Connect_Click(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
if (Client_ServerIpComboBox.Text != "" && Client_PortComboBox.SelectedItem != null)
|
{
|
string ipAddress = Client_ServerIpComboBox.Text;
|
int port = int.Parse(Client_PortComboBox.Text);
|
|
// 保存连接信息用于重连
|
_lastIpAddress = ipAddress;
|
_lastPort = port;
|
|
modbusTCPClient.ModbudTCP_Connect(ipAddress, port);
|
if (modbusTCPClient._client == null)
|
{
|
//MessageBox.Show("连接到服务器失败,请检查连接后重试");
|
return;
|
}
|
|
// 初始化重连定时器
|
InitializeReconnectTimer();
|
|
// 创建定时器,作为ModBus心跳信号
|
heartbeatTimer = new System.Threading.Timer(HeartbeatCallback, null, Timeout.Infinite, heartbeatInterval);
|
// 启动定时器,立即开始并每隔heartbeatInterval毫秒执行一次
|
heartbeatTimer.Change(0, heartbeatInterval);
|
// 开始侦听客户端触发信号
|
Task.Run(() => ClientListen());
|
GetMessage_Modbus($"连接成功 {ipAddress}:{port}\n");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "ModBus已连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
}));
|
}
|
else
|
{
|
MessageBox.Show("请输入正确的IP和端口");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
return;
|
}
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show("地址和端口已被占用");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
return;
|
}
|
}
|
//ModBus断开连接
|
private void Client_Disconnect_Click(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
// 停止所有定时器
|
heartbeatTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
_reconnectTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
|
if (modbusTCPClient._client != null && modbusTCPClient._client.Connected)
|
{
|
modbusTCPClient._client?.Close();
|
modbusTCPClient._client = null;
|
GetMessage_Modbus("连接已断开\n");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
}
|
|
// 重置重连状态
|
_reconnectAttempts = 0;
|
_isReconnecting = false;
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show("连接断开");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
}
|
}
|
|
private void Client_ClearClientLogs_Click(object sender, RoutedEventArgs e)
|
{
|
Client_LogsTextBox.Clear();
|
}
|
#endregion
|
#region 图像采集与处理模块
|
//获取图像并处理
|
private void GetImage()
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DetectState.Text = "正在检测中。。。";
|
DetectState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
}));
|
//计时器启动
|
stopwatch.Reset();
|
stopwatch.Start();
|
Console.WriteLine($"计时器启动!");
|
//加载上次解决方案
|
bool isL = LoadLastUsedConfiguration(false);
|
if (!isL)
|
{
|
stopwatch.Stop();
|
long F_elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
|
Console.WriteLine($"系统响应时间为:{F_elapsedMilliseconds}ms");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DetectState.Text = "未在检测";
|
DetectState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
return;
|
}
|
for (int i = 0; i < DeviceListBox.Items.Count; i++)
|
{
|
//采集图像
|
GetIDDevice_CaptureImage(i + 1);
|
}
|
for (int i = 0; i < DeviceListBox.Items.Count; i++)
|
{
|
//处理图像
|
Reasoning_Image(i + 1);
|
}
|
stopwatch.Stop();
|
long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
|
Console.WriteLine($"系统响应时间为:{elapsedMilliseconds}ms");
|
EnhancedLogViewModel.Instance.AddLog($"系统响应时间为:{elapsedMilliseconds}ms");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
DetectState.Text = "未在检测";
|
DetectState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
//NG图像弹窗显示与保存
|
if (Image_NG.Count != 0)
|
{
|
Task.Run(() =>
|
{
|
List<string> Image_NG_Save = new List<string>(Image_NG);
|
|
// NG图像弹窗显示
|
OnDetectionCompleted(Image_NG);
|
// NG图像自动保存
|
int savedCount = AutoSaveNGImages(Image_NG_Save);
|
EnhancedLogViewModel.Instance.AddLog($"成功保存了 {savedCount} 张NG图片");
|
Image_NG_Save.Clear();
|
});
|
|
}
|
|
//检测结果通过ModBus存入寄存器
|
try
|
{
|
if (modbusTCPClient._client != null)
|
{
|
if (!IsSignleOutput)
|
{
|
// 将二进制数组转换为ushort
|
ushort value = BinaryToUshort_MSBFirst(usOutput);//1号-16号相机
|
ushort value2 = BinaryToUshort_MSBFirst(usOutput2);//17-20号相机
|
// 将ushort存储在ushort数组中
|
ushort[] test = new ushort[] { value };
|
ushort[] test2 = new ushort[] { value2 };
|
modbusTCPClient.MultipleRegistersWrite(3, test);//1号-16号相机
|
modbusTCPClient.MultipleRegistersWrite(4, test2);//17-20号相机
|
EnhancedLogViewModel.Instance.AddLog($"检测结果保持{Hold_Time}秒");
|
if (double.TryParse(Hold_Time, out double interval))
|
{
|
OutputTimer = new System.Timers.Timer(interval * 1000);
|
}
|
else
|
{
|
MessageBox.Show("保持时间格式错误,请检查配置", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
return;
|
}
|
|
OutputTimer.Elapsed += OnTimedEvent;
|
OutputTimer.AutoReset = false; // 设置为false表示只触发一次
|
OutputTimer.Start();
|
}
|
else
|
{
|
if (USOUT)
|
{
|
modbusTCPClient.MultipleRegistersWrite(3, new ushort[] { 1 });
|
EnhancedLogViewModel.Instance.AddLog($"检测结果保持5秒");
|
OutputTimer = new System.Timers.Timer(5000);
|
OutputTimer.Elapsed += OnTimedEvent;
|
OutputTimer.AutoReset = false; // 设置为false表示只触发一次
|
OutputTimer.Start();
|
}
|
else
|
{
|
modbusTCPClient.MultipleRegistersWrite(3, new ushort[] { 0 });
|
}
|
|
}
|
}
|
else if (TcpServerManager._isRunning)
|
{
|
//usOutput_tcp
|
}
|
else
|
{
|
// 获取当前日期
|
DateTime currentDate = DateTime.Now;
|
// 格式化时间为 "HHmmss"
|
string timeFileName = currentDate.ToString("HH:mm:ss");
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
//MessageBox.Show($"ModBus未连接", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
GetMessage_Modbus($"{timeFileName} ModBus未连接");
|
}
|
USOUT = true;
|
}
|
catch (NullReferenceException ex)
|
{
|
MessageBox.Show($"ModBus未连接:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
USOUT = true;
|
}
|
private ImageDisplayWindow _imageDisplayWindow;
|
|
//NG图像弹窗显示
|
private void OnDetectionCompleted(List<string> imagePath)
|
{
|
if (imagePath.Count != 0)
|
{
|
// 使用Dispatcher确保UI线程操作
|
Dispatcher.Invoke(() =>
|
{
|
// 检查窗口是否已存在
|
if (_imageDisplayWindow == null || !_imageDisplayWindow.IsLoaded)
|
{
|
_imageDisplayWindow = new ImageDisplayWindow();
|
_imageDisplayWindow.Closed += (s, e) => { _imageDisplayWindow = null; };
|
_imageDisplayWindow.Show();
|
_imageDisplayWindow.Topmost = true;
|
}
|
|
// 添加图片到查看器
|
_imageDisplayWindow.AddImage(imagePath);
|
});
|
Image_NG.Clear();
|
}
|
}
|
//图像处理
|
private void Reasoning_Image(int Sequence)
|
{
|
IntPtr deviceHandle = _deviceHandles[Sequence];
|
IntPtr imagePtr = _imagePtr[Sequence];
|
|
int[] classIds; //目标物类别
|
int[] numBoxes; //目标物数量
|
float[] prob; //目标物得分
|
float[] x1 = new float[100], y1 = new float[100], x2 = new float[100], y2 = new float[100];
|
if (imagePtr == IntPtr.Zero)
|
{
|
GetMessage($"设备{Sequence}连接已断开");
|
EnhancedLogViewModel.Instance.AddLog($"设备{Sequence}连接已断开", "ERROR");
|
return;
|
}
|
long Image_Width = IDImage_Width(imagePtr);
|
long Image_Height = IDImage_Height(imagePtr);
|
long Image_Channels = IDImage_Channels(imagePtr);
|
long dataLength = Image_Width * Image_Height * Image_Channels;
|
byte[] Imagedata = new byte[dataLength];
|
byte[] bytes = new byte[Image_Width * Image_Height * 3];
|
IntPtr Image_ImageData = IDImage_ImageData(imagePtr);
|
|
if (imagePtr == IntPtr.Zero)
|
{
|
MessageBox.Show("图像句柄无效");
|
}
|
if (dataLength != 0)
|
{
|
Console.WriteLine($"获取日期");
|
// 获取当前日期
|
DateTime currentDate = DateTime.Now;
|
|
// 格式化日期为 "yyyyMMdd"
|
string datePath = currentDate.ToString("yyyyMMdd");
|
|
// 格式化时间为 "HHmmss"
|
string timeFileName = currentDate.ToString("HH_mm_ss");
|
|
// 构建完整路径
|
string folderPath = $@"{DownloadData.ImageSavingPath}\{datePath}";
|
string filePath = Path.Combine(folderPath, $"{timeFileName + "_" + Sequence + DownloadData.ImageFormat_main}");
|
|
// 检查文件夹是否存在,如果不存在则创建
|
if (!Directory.Exists(folderPath))
|
{
|
Directory.CreateDirectory(folderPath);
|
}
|
Console.WriteLine($"图像句柄转换为字节数据");
|
Marshal.Copy(Image_ImageData, Imagedata, 0, (int)dataLength); //图像句柄转换为字节数据
|
ConvertSingletoThreeChannels(detector, Imagedata, (int)Image_Width, (int)Image_Height, bytes);
|
//原图保存至本地
|
if (DownloadData.ImageSave)
|
{
|
IDImage_SaveImage(imagePtr, filePath, DownloadData.ImageCompressionRatio_main);
|
EnhancedLogViewModel.Instance.AddLog($"设备{Sequence}图像已保存至{filePath}");
|
}
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:{Sequence}号设备图像预处理完成,开始进行算法推理");
|
//深度学习推理模型
|
Reasoning_AI(detector, bytes, (int)Image_Width, (int)Image_Height, out classIds, out numBoxes, out prob, out x1, out y1, out x2, out y2, Sequence);
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:{Sequence}号设备算法推理完成,开始进行结果判断");
|
//结果判断
|
switch (Sequence)
|
{
|
case 1:
|
int isPass1 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass1;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass1;
|
|
if (isPass1 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result0.Content = "OK";
|
finall_result0.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result0.Content = "NG";
|
finall_result0.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 2:
|
int isPass2 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass2;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass2;
|
if (isPass2 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result1.Content = "OK";
|
finall_result1.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result1.Content = "NG";
|
finall_result1.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 3:
|
int isPass3 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass3;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass3;
|
if (isPass3 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result2.Content = "OK";
|
finall_result2.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result2.Content = "NG";
|
finall_result2.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 4:
|
int isPass4 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass4;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass4;
|
if (isPass4 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result3.Content = "OK";
|
finall_result3.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result3.Content = "NG";
|
finall_result3.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 5:
|
int isPass5 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass5;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass5;
|
if (isPass5 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result4.Content = "OK";
|
finall_result4.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result4.Content = "NG";
|
finall_result4.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 6:
|
int isPass6 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass6;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass6;
|
if (isPass6 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result5.Content = "OK";
|
finall_result5.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result5.Content = "NG";
|
finall_result5.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 7:
|
int isPass7 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass7;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass7;
|
if (isPass7 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result6.Content = "OK";
|
finall_result6.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result6.Content = "NG";
|
finall_result6.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 8:
|
int isPass8 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass8;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass8;
|
if (isPass8 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result7.Content = "OK";
|
finall_result7.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result7.Content = "NG";
|
finall_result7.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 9:
|
int isPass9 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass9;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass9;
|
if (isPass9 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result8.Content = "OK";
|
finall_result8.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result8.Content = "NG";
|
finall_result8.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 10:
|
int isPass10 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass10;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass10;
|
if (isPass10 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result9.Content = "OK";
|
finall_result9.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result9.Content = "NG";
|
finall_result9.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 11:
|
int isPass11 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass11;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass11;
|
if (isPass11 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result10.Content = "OK";
|
finall_result10.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result10.Content = "NG";
|
finall_result10.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 12:
|
int isPass12 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass12;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass12;
|
if (isPass12 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result11.Content = "OK";
|
finall_result11.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
//Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result11.Content = "NG";
|
finall_result11.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 13:
|
int isPass13 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass13;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass13;
|
if (isPass13 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result12.Content = "OK";
|
finall_result12.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result12.Content = "NG";
|
finall_result12.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 14:
|
int isPass14 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass14;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass14;
|
if (isPass14 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result13.Content = "OK";
|
finall_result13.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result13.Content = "NG";
|
finall_result13.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 15:
|
int isPass15 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass15;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass15;
|
if (isPass15 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result14.Content = "OK";
|
finall_result14.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result14.Content = "NG";
|
finall_result14.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 16:
|
int isPass16 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput[Sequence - 1] = isPass16;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass16;
|
if (isPass16 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result15.Content = "OK";
|
finall_result15.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result15.Content = "NG";
|
finall_result15.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 17:
|
int isPass17 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput2[Sequence - 17] = isPass17;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass17;
|
if (isPass17 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result16.Content = "OK";
|
finall_result16.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result16.Content = "NG";
|
finall_result16.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 18:
|
int isPass18 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput2[Sequence - 17] = isPass18;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass18;
|
if (isPass18 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result17.Content = "OK";
|
finall_result17.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result17.Content = "NG";
|
finall_result17.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 19:
|
int isPass19 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput2[Sequence - 17] = isPass19;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass19;
|
if (isPass19 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result18.Content = "OK";
|
finall_result18.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result18.Content = "NG";
|
finall_result18.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
case 20:
|
int isPass20 = config.JudgeDetectionResult(Sequence, numBoxes, classIds, prob);
|
usOutput2[Sequence - 17] = isPass20;
|
if (TcpServerManager._isRunning && usOutput_tcp != null) usOutput_tcp[Sequence - 1] = isPass20;
|
if (isPass20 == 1)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result19.Content = "OK";
|
finall_result19.Background = System.Windows.Media.Brushes.Green;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测通过");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "OK");
|
});
|
}
|
else
|
{
|
USOUT = false;
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result19.Content = "NG";
|
finall_result19.Background = System.Windows.Media.Brushes.Red;
|
}));
|
Console.WriteLine($"点位 {Sequence} 检测不通过");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:点位 {Sequence} 检测不通过", "ERROR");
|
Image_NG.Add($".\\vino_res\\result_{Sequence}.jpg");
|
Task.Run(() =>
|
{
|
// 记录到Excel(批量写入)
|
ExcelResultRecorder.RecordDetectionResult(Sequence, "NG");
|
});
|
}
|
break;
|
}
|
}
|
}
|
//图像采集
|
private void GetIDDevice_CaptureImage(int Sequence)
|
{
|
IntPtr deviceHandle = _deviceHandles[Sequence];
|
IntPtr imagePtr = _imagePtr[Sequence];
|
|
// 开始采集图像
|
Console.WriteLine($"{Sequence}号设备开始采集图像");
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:{Sequence}号设备开始采集图像");
|
long rel = IDDevice_IsOpen(deviceHandle);
|
if (rel == 0)
|
{
|
MessageBox.Show($"设备{Sequence}连接已断开", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
EnhancedLogViewModel.Instance.AddLog($"设备{Sequence}连接已断开", "ERROR");
|
_imagePtr[Sequence] = IntPtr.Zero;
|
return;
|
}
|
|
IDDevice_CaptureImage(deviceHandle, imagePtr);
|
EnhancedLogViewModel.Instance.AddLog($"{DateTime.Now:HH:mm:ss:fff}:{Sequence}号设备图像采集结束,开始进行图像预处理");
|
}
|
#endregion
|
// 数据转换
|
static ushort BinaryToUshort_MSBFirst(int[] binaryArray)
|
{
|
if (binaryArray.Length > 16)
|
throw new ArgumentException("Binary array cannot exceed 16 bits.");
|
|
ushort result = 0;
|
for (int i = 0; i < binaryArray.Length; i++)
|
{
|
if (binaryArray[i] == 1)
|
result |= (ushort)(1 << i); // 低位在前
|
else if (binaryArray[i] != 0)
|
throw new ArgumentException("Binary array can only contain 0s and 1s.");
|
}
|
return result;
|
}
|
/// <summary>
|
/// 自动保存NG图片到指定日期目录
|
/// 保存路径格式:D:\01 LBImage_NG\(当前日期)\
|
/// 如果目录不存在会自动创建,支持批量保存操作
|
/// </summary>
|
/// <param name="ngImagePaths">NG图片路径集合</param>
|
/// <returns>成功保存的图片数量</returns>
|
public int AutoSaveNGImages(List<string> ngImagePaths)
|
{
|
// 校验输入参数
|
if (ngImagePaths == null || ngImagePaths.Count == 0)
|
{
|
EnhancedLogViewModel.Instance.AddLog($"NG图片路径集合为空,无需保存操作。");
|
return 0;
|
}
|
|
int successCount = 0; // 成功保存的计数器
|
string baseDirectory = @"D:\01 LBImage_NG"; // 基础保存目录
|
|
try
|
{
|
// 获取当前系统日期,格式化为yyyyMMdd
|
string dateFolderName = DateTime.Now.ToString("yyyyMMdd");
|
|
// 构建完整的目标目录路径
|
string targetDirectory = Path.Combine(baseDirectory, dateFolderName);
|
|
// 如果目标目录不存在,则创建
|
if (!Directory.Exists(targetDirectory))
|
{
|
Directory.CreateDirectory(targetDirectory);
|
}
|
|
// 遍历所有NG图片路径
|
foreach (string sourcePath in ngImagePaths)
|
{
|
try
|
{
|
// 检查源文件是否存在
|
if (!File.Exists(sourcePath))
|
{
|
Console.WriteLine($"文件不存在,跳过: {sourcePath}");
|
continue;
|
}
|
|
// 获取文件名(包含扩展名)
|
string fileName = Path.GetFileName(sourcePath);
|
|
// 构建目标文件完整路径
|
string destinationPath = Path.Combine(targetDirectory, fileName);
|
|
// 如果目标文件已存在,添加时间戳避免覆盖
|
if (File.Exists(destinationPath))
|
{
|
string timeStamp = DateTime.Now.ToString("HHmmss");
|
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
|
string extension = Path.GetExtension(fileName);
|
fileName = $"{fileNameWithoutExtension}_{timeStamp}{extension}";
|
destinationPath = Path.Combine(targetDirectory, fileName);
|
}
|
|
// 复制文件到目标目录
|
File.Copy(sourcePath, destinationPath, true);
|
successCount++;
|
|
Console.WriteLine($"成功保存: {sourcePath} -> {destinationPath}");
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine($"保存文件失败 {sourcePath}: {ex.Message}");
|
}
|
}
|
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"保存过程中发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
|
return successCount;
|
}
|
//默认加载上次检测方案
|
public bool LoadLastUsedConfiguration(bool bl)
|
{
|
bool isLoad = true;
|
try
|
{
|
if (!string.IsNullOrEmpty(ResultJudge.AppSettings.LastConfigFilePath_Proj) && File.Exists(ResultJudge.AppSettings.LastConfigFilePath_Proj))
|
{
|
bool isLoadModel;
|
//json = File.ReadAllText(ResultJudge.AppSettings.LastConfigFilePath);
|
var (modelName, configPath, configContent, message) = LBProjService.LoadLBProj(ResultJudge.AppSettings.LastConfigFilePath_Proj);
|
config = JsonConvert.DeserializeObject<ResultJudge.JudgmentConfiguration>(configContent);
|
|
if (bl)
|
{
|
if (detector != IntPtr.Zero)
|
{
|
DisposeDetector_CPU(detector);
|
}
|
Task.Run(() =>
|
{
|
// 模型推理引擎选择
|
detector = CreateDetector_CPU();
|
isLoadModel = InitializeDetector_CPU(detector, Detector_Device, $".\\model\\{modelName}");
|
while (true)
|
{
|
if (isLoadModel)
|
{
|
EnhancedLogViewModel.Instance.AddLog($"模型编译成功");
|
break;
|
}
|
}
|
});
|
MessageBox.Show($"已自动加载上次使用的工程文件: {ResultJudge.AppSettings.LastConfigFilePath_Proj}",
|
"成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
}
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
ProjectState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
ModelState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
ProjectState.Text = ResultJudge.AppSettings.LastConfigFilePath_Proj;
|
ModelState.Text = modelName;
|
}));
|
EnhancedLogViewModel.Instance.AddLog($"当前工程文件: {ResultJudge.AppSettings.LastConfigFilePath_Proj},模型:{modelName}");
|
isLoad = true;
|
}
|
else
|
{
|
if (!string.IsNullOrEmpty(ResultJudge.AppSettings.LastConfigFilePath) && File.Exists(ResultJudge.AppSettings.LastConfigFilePath))
|
{
|
json = File.ReadAllText(ResultJudge.AppSettings.LastConfigFilePath);
|
config = JsonConvert.DeserializeObject<ResultJudge.JudgmentConfiguration>(json);
|
if (bl)
|
{
|
MessageBox.Show($"已自动加载上次使用的检测方案: {ResultJudge.AppSettings.LastConfigFilePath}",
|
"成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
}
|
EnhancedLogViewModel.Instance.AddLog($"当前检测方案: {ResultJudge.AppSettings.LastConfigFilePath}");
|
isLoad = true;
|
}
|
else
|
{
|
MessageBox.Show("没有找到上次使用的检测方案,请手动加载",
|
"提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
EnhancedLogViewModel.Instance.AddLog($"没有找到上次使用的检测方案,请手动加载", "WARN");
|
isLoad = false;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
isLoad = false;
|
MessageBox.Show($"自动加载工程时出错,请手动加载: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
return isLoad;
|
}
|
#endregion
|
#region Modbus Tcp通讯设置
|
//记录最后一次触发时间
|
private DateTime _lastTriggerTime = DateTime.MinValue;
|
//触发信号监听
|
private void ClientListen()
|
{
|
try
|
{
|
int num = 0;
|
while (modbusTCPClient._client == null || modbusTCPClient._client.Connected == false || modbusTCPClient._master == null)
|
{
|
if (_isReconnecting) return; // 如果正在重连,直接返回
|
|
modbusTCPClient.ModbudTCP_Connect(_lastIpAddress, _lastPort);
|
if (num++ > 3)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
MessageBox.Show("Modbus master 未初始化。无法连接PLC");
|
}));
|
break;
|
}
|
}
|
|
while (modbusTCPClient._client != null && modbusTCPClient._client.Connected) //持续监控
|
{
|
//modbusTCPClient.currentValus_ROIModel = modbusTCPClient.InputRegistersRead(3);
|
while (modbusTCPClient._client != null && modbusTCPClient._client.Connected)
|
{
|
modbusTCPClient.currentValus_trigger = modbusTCPClient.InputRegistersRead(3);
|
if (modbusTCPClient.previousValus_trigger[0] == 0 && modbusTCPClient.currentValus_trigger[0] == 1)
|
{
|
// 检查距离上次触发是否超过5秒
|
if ((DateTime.Now - _lastTriggerTime).TotalSeconds >= double.Parse(Selflocking_Time))
|
{
|
_lastTriggerTime = DateTime.Now;
|
modbusTCPClient.istrigger = true;
|
Dispatcher.Invoke(() =>
|
{
|
DateTime currentDate = DateTime.Now;
|
string timeFileName = currentDate.ToString("HH:mm:ss");
|
GetMessage_Modbus($"检测到触发信号:{modbusTCPClient.currentValus_trigger[0]}");
|
GetMessage_Modbus($"{timeFileName}\n");
|
});
|
Console.WriteLine($"检测到触发信号:{modbusTCPClient.currentValus_trigger[0]}");
|
modbusTCPClient.MultipleRegistersWrite(3, new ushort[] { 0 });
|
Console.WriteLine($"寄存器置0");
|
ReSetUI();
|
Task.Run(() => GetImage());
|
}
|
else
|
{
|
Console.WriteLine($"忽略触发信号,距离上次触发不足{Selflocking_Time}秒");
|
modbusTCPClient.MultipleRegistersWrite(3, new ushort[] { 0 });
|
}
|
}
|
modbusTCPClient.previousValus_trigger = modbusTCPClient.currentValus_trigger;
|
modbusTCPClient.istrigger = false;
|
break;
|
}
|
modbusTCPClient.previousValus_ROIModel = modbusTCPClient.currentValus_ROIModel;
|
}
|
}
|
catch (Exception e)
|
{
|
// 如果正在重连,不显示错误消息
|
if (!_isReconnecting)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
// 不再弹窗,只在日志中记录
|
GetMessage_Modbus("Modbus连接断开,开始尝试重连...\n");
|
}));
|
}
|
}
|
}
|
//ModBus心跳信号
|
private void HeartbeatCallback(object state)
|
{
|
try
|
{
|
// 读取保持寄存器1的值
|
modbusTCPClient.HoldingRegisterRead(1);
|
Console.WriteLine("心跳信号收发正常");
|
|
// 心跳正常,重置重连尝试次数
|
_reconnectAttempts = 0;
|
}
|
catch (Exception ex)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
GetMessage_Modbus("检测到Modbus连接异常,准备重连...\n");
|
}));
|
Console.WriteLine($"Heartbeat failed: {ex.Message}");
|
|
// 立即启动重连机制
|
StartReconnect();
|
}
|
}
|
// 用户点击确定跟踪标志位
|
private bool _disconnectAlertShown = false;
|
// 设备连接状态检测
|
private void DeviceConnectbeatCallback(object state)
|
{
|
try
|
{
|
for (int i = 0; i < DeviceListBox.Items.Count; i++)
|
{
|
IntPtr deviceHandle = _deviceHandles[i + 1];
|
long rel = IDDevice_IsOpen(deviceHandle);
|
if (rel == 0)
|
{
|
if (!_disconnectAlertShown)
|
{
|
_disconnectAlertShown = true;
|
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
{
|
MessageBox.Show($"设备{i + 1}连接断开,请重新连接", "错误",
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
_disconnectAlertShown = false; // 用户点击确定后重置标志
|
});
|
|
_imagePtr[i + 1] = IntPtr.Zero;
|
// 彻底释放定时器
|
deviceStatusTimer?.Dispose();
|
deviceStatusTimer = null;
|
}
|
return;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
Console.WriteLine($"设备未按照映射表连接: {ex.Message}");
|
}
|
}
|
#endregion
|
|
#region Modbus重连机制
|
|
// 初始化重连定时器
|
private void InitializeReconnectTimer()
|
{
|
// 如果定时器已存在,先释放
|
_reconnectTimer?.Dispose();
|
|
// 创建新的重连定时器
|
_reconnectTimer = new System.Threading.Timer(ReconnectCallback, null, Timeout.Infinite, RECONNECT_INTERVAL);
|
}
|
|
// 启动重连
|
private void StartReconnect()
|
{
|
if (_isReconnecting) return;
|
|
// 停止心跳定时器
|
heartbeatTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
|
// 启动重连定时器
|
_reconnectTimer?.Change(0, RECONNECT_INTERVAL);
|
}
|
|
// 停止重连
|
private void StopReconnect()
|
{
|
// 停止重连定时器
|
_reconnectTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
|
// 重启心跳定时器
|
heartbeatTimer?.Change(0, heartbeatInterval);
|
}
|
|
// 重连回调
|
private void ReconnectCallback(object state)
|
{
|
if (_isReconnecting) return;
|
|
_isReconnecting = true;
|
|
try
|
{
|
// 检查是否超过最大重连次数
|
if (_reconnectAttempts >= MAX_RECONNECT_ATTEMPTS)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
GetMessage_Modbus($"重连失败,已达到最大重连次数 ({MAX_RECONNECT_ATTEMPTS})\n");
|
// 只有超过最大重连次数时才弹窗
|
MessageBox.Show("Modbus重连失败,已达到最大重连次数", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}));
|
|
// 停止重连定时器
|
_reconnectTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
return;
|
}
|
|
_reconnectAttempts++;
|
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
GetMessage_Modbus($"尝试第 {_reconnectAttempts} 次重连...\n");
|
}));
|
|
// 尝试重连
|
bool reconnectSuccess = modbusTCPClient.Reconnect(_lastIpAddress, _lastPort);
|
|
if (reconnectSuccess)
|
{
|
// 重连成功
|
_reconnectAttempts = 0;
|
_isReconnecting = false;
|
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
GetMessage_Modbus("重连成功\n");
|
LinkState.Text = "ModBus已连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
}));
|
|
// 停止重连,恢复心跳
|
StopReconnect();
|
|
// 重新启动监听任务
|
Task.Run(() => ClientListen());
|
}
|
else
|
{
|
// 重连失败,继续尝试,不在UI上弹窗,只在日志中记录
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
GetMessage_Modbus($"第 {_reconnectAttempts} 次重连失败\n");
|
}));
|
|
_isReconnecting = false;
|
}
|
}
|
catch (Exception ex)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
GetMessage_Modbus($"重连过程中发生错误: {ex.Message}\n");
|
}));
|
|
_isReconnecting = false;
|
}
|
}
|
|
#endregion
|
|
// 通讯测试,debug用
|
private void Write_Click(object sender, RoutedEventArgs e)
|
{
|
EnhancedLogViewModel.Instance.AddLog("开始ModBus通讯测试,所有寄存器写入高电平2s后置零", "DEBUG");
|
if (modbusTCPClient._client == null)
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}));
|
MessageBox.Show("连接到服务器失败,请检查连接后重试");
|
return;
|
}
|
//ushort[] test = new ushort[] { 0x8001 };
|
//modbusTCPClient.MultipleRegistersWrite(3, test);
|
//outputs[0] = true;
|
//outputs[15] = true;
|
//ushort value = BoolsToUshort(outputs);
|
// 假设有一个包含16个0和1的数组
|
int[] binaryDigits = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
int[] binaryDigits2 = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
|
// 将二进制数组转换为ushort
|
ushort value = BinaryToUshort_MSBFirst(binaryDigits);
|
ushort value2 = BinaryToUshort_MSBFirst(binaryDigits2);
|
|
// 将ushort存储在ushort数组中
|
ushort[] test = new ushort[] { value };
|
ushort[] test2 = new ushort[] { value2 };
|
|
modbusTCPClient.MultipleRegistersWrite(3, test);
|
modbusTCPClient.MultipleRegistersWrite(4, test2);
|
Thread.Sleep(2000);
|
modbusTCPClient.MultipleRegistersWrite(3, new ushort[] { 0 });
|
modbusTCPClient.MultipleRegistersWrite(4, new ushort[] { 0 });
|
}
|
private void OnTimedEvent(object source, ElapsedEventArgs e)
|
{
|
// 定时器触发时执行的代码
|
modbusTCPClient.MultipleRegistersWrite(3, new ushort[] { 0 });
|
modbusTCPClient.MultipleRegistersWrite(4, new ushort[] { 0 });
|
EnhancedLogViewModel.Instance.AddLog($"Modbus已置零");
|
Console.WriteLine("Modbus已置零");
|
|
}
|
// 手动采集图像
|
private void Read_Click(object sender, RoutedEventArgs e)
|
{
|
EnhancedLogViewModel.Instance.AddLog("开始手动采集图像", "DEBUG");
|
ReSetUI();
|
Task.Run(() =>
|
{
|
GetImage();
|
});
|
}
|
private void ReSetUI()
|
{
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
Finall_result0.Content = "";
|
finall_result0.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result1.Content = "";
|
finall_result1.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result2.Content = "";
|
finall_result2.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result3.Content = "";
|
finall_result3.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result4.Content = "";
|
finall_result4.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result5.Content = "";
|
finall_result5.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result6.Content = "";
|
finall_result6.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result7.Content = "";
|
finall_result7.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result8.Content = "";
|
finall_result8.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result9.Content = "";
|
finall_result9.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result10.Content = "";
|
finall_result10.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result11.Content = "";
|
finall_result11.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result12.Content = "";
|
finall_result12.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result13.Content = "";
|
finall_result13.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result14.Content = "";
|
finall_result14.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result15.Content = "";
|
finall_result15.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result16.Content = "";
|
finall_result16.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result17.Content = "";
|
finall_result17.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result18.Content = "";
|
finall_result18.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result19.Content = "";
|
finall_result19.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result20.Content = "";
|
finall_result20.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result21.Content = "";
|
finall_result21.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result22.Content = "";
|
finall_result22.Background = System.Windows.Media.Brushes.Gray;
|
Finall_result23.Content = "";
|
finall_result23.Background = System.Windows.Media.Brushes.Gray;
|
}));
|
}
|
private void ReSet_Click(object sender, RoutedEventArgs e)
|
{
|
ReSetUI();
|
}
|
//设备管理
|
SmartScanner.ProductManager productManager = null;
|
private void ProductMaanager_Btn_Click(object sender, RoutedEventArgs e)
|
{
|
var loginWindow = new LoginWindow();
|
if (loginWindow.ShowDialog() == true)
|
{
|
if (productManager == null || !productManager.IsLoaded)
|
{
|
productManager = new ProductManager();
|
productManager.Closed += (s, args) => { productManager = null; };
|
productManager.SetControlsEnabled(UserManager.HasAdministratorPrivilege());
|
productManager.ShowDialog();
|
}
|
else
|
{
|
if (productManager.WindowState == WindowState.Minimized)
|
{
|
productManager.WindowState = WindowState.Normal; // 恢复窗口状态
|
}
|
productManager.Activate(); // 如果窗口已存在,则激活它
|
}
|
}
|
}
|
//检测方案
|
SmartScanner.ResultJudge resultJudge = null;
|
private void ResultJudge_Btn_Click(object sender, RoutedEventArgs e)
|
{
|
var loginWindow = new LoginWindow();
|
if (loginWindow.ShowDialog() == true)
|
{
|
if (resultJudge == null || !resultJudge.IsLoaded)
|
{
|
resultJudge = new ResultJudge();
|
resultJudge.Closed += (s, args) => { resultJudge = null; };
|
resultJudge.SetControlsEnabled(UserManager.HasAdministratorPrivilege());
|
resultJudge.ShowDialog();
|
}
|
else
|
{
|
if (resultJudge.WindowState == WindowState.Minimized)
|
{
|
resultJudge.WindowState = WindowState.Normal; // 恢复窗口状态
|
}
|
resultJudge.Activate(); // 如果窗口已存在,则激活它
|
}
|
}
|
}
|
#region 输出模式选择
|
private void OutputCheckBox_Checked(object sender, RoutedEventArgs e)
|
{
|
IsSignleOutput = true;
|
// 记录日志
|
OperateLogService.LogOperation(
|
"结果输出模式",
|
$"修改为: 单点输出",
|
null);
|
}
|
|
private void OutputCheckBox_Unchecked(object sender, RoutedEventArgs e)
|
{
|
IsSignleOutput = false;
|
// 记录日志
|
OperateLogService.LogOperation(
|
"结果输出模式",
|
$"修改为: 多点输出",
|
null);
|
}
|
#endregion
|
// 图像保存设置
|
SmartScanner.DownloadData downloadData = null;
|
private void ImageSetup_Btn_Click(object sender, RoutedEventArgs e)
|
{
|
var loginWindow = new LoginWindow();
|
if (loginWindow.ShowDialog() == true)
|
{
|
if (downloadData == null || !downloadData.IsLoaded)
|
{
|
downloadData = new DownloadData();
|
downloadData.Closed += (s, args) => { downloadData = null; };
|
downloadData.SetControlsEnabled(UserManager.HasAdministratorPrivilege());
|
downloadData.ShowDialog();
|
}
|
else
|
{
|
if (downloadData.WindowState == WindowState.Minimized)
|
{
|
downloadData.WindowState = WindowState.Normal; // 恢复窗口状态
|
}
|
downloadData.Activate(); // 如果窗口已存在,则激活它
|
}
|
}
|
}
|
private void AddTestLog_Click(object sender, RoutedEventArgs e)
|
{
|
EnhancedLogViewModel.Instance.AddLog("这是一条普通信息");
|
EnhancedLogViewModel.Instance.AddLog("这是一条警告信息", "WARN");
|
EnhancedLogViewModel.Instance.AddLog("这是一条错误信息", "ERROR");
|
EnhancedLogViewModel.Instance.AddLog("这是一条调试信息", "DEBUG");
|
}
|
private void TCPClient_Connect_Click(object sender, RoutedEventArgs e)
|
{
|
|
}
|
|
private void TCPClient_ClearClientLogs_Click(object sender, RoutedEventArgs e)
|
{
|
|
}
|
|
private void btnViewLogs_Click(object sender, RoutedEventArgs e)
|
{
|
var operateLogView = new OperateLogView();
|
operateLogView.ShowDialog();
|
}
|
|
private void btnViewReports_Click(object sender, RoutedEventArgs e)
|
{
|
ExcelResultRecorder.OpenReportFolder();
|
}
|
|
private async void RestartButton_Click(object sender, RoutedEventArgs e)
|
{
|
if (MessageBox.Show("确定要重启应用程序吗?", "确认重启",
|
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
{
|
Mouse.OverrideCursor = Cursors.Wait;
|
try
|
{
|
await AppRestartHelper.RestartAsync();
|
}
|
finally
|
{
|
Mouse.OverrideCursor = null;
|
}
|
}
|
}
|
#region 界面图片显示按钮
|
private ImageDisplayWindow displayWindow;
|
|
private void finall_result0_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_1.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_2.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_3.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result3_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_4.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result4_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_5.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result5_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_6.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result6_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_7.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result7_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_8.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result8_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_9.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result9_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_10.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result10_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_11.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result11_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_12.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result12_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_13.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result13_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_14.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result14_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_15.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result15_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_16.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result16_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_17.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result17_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_18.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result18_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_19.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result19_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_20.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result20_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_21.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result21_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_22.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
private void finall_result22_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_23.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
|
private void finall_result23_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
{
|
displayWindow = new ImageDisplayWindow();
|
bool isShow = displayWindow.ShowImage_main(".\\vino_res\\result_24.jpg");
|
if (isShow)
|
{
|
displayWindow.Show();
|
}
|
else
|
{
|
return;
|
}
|
|
}
|
#endregion
|
#region TCP/IP通讯模块
|
private void TCPServer_Start_Click(object sender, RoutedEventArgs e)
|
{
|
try
|
{
|
var ip = GetSelectedIP();
|
var port = GetSelectedPort();
|
var enableHeartbeat = TCPServer_EnableHeartbeat.IsChecked ?? false;
|
var heartbeatCommand = TCPServer_HeartbeatCommand.Text.Trim();
|
var heartbeatInterval = int.Parse(TCPServer_HeartbeatInterval.Text);
|
var outputIOCount = DeviceListBox.Items.Count;
|
|
// 验证心跳设置
|
if (enableHeartbeat)
|
{
|
if (string.IsNullOrWhiteSpace(heartbeatCommand))
|
{
|
MessageBox.Show("请输入有效的心跳指令");
|
return;
|
}
|
|
if (heartbeatInterval <= 0)
|
{
|
MessageBox.Show("心跳间隔必须大于0");
|
return;
|
}
|
}
|
|
_tcpServerManager = new TcpServerManager(
|
enableHeartbeat,
|
heartbeatCommand,
|
heartbeatInterval,
|
GetImageAndProcess,
|
outputIOCount);
|
|
_tcpServerManager.LogMessage += msg => Dispatcher.Invoke(() =>
|
{
|
TCPServer_LogsTextBox.AppendText($"{DateTime.Now:HH:mm:ss:fff} {msg}\n");
|
TCPServer_LogsTextBox.ScrollToEnd();
|
});
|
|
_ = _tcpServerManager.StartAsync(ip, port);
|
|
TCPServer_Start.IsEnabled = false;
|
TCPServer_Stop.IsEnabled = true;
|
LinkState.Text = "TCP已启动";
|
LinkState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"启动服务器失败: {ex.Message}");
|
}
|
}
|
private async Task<int[]> GetImageAndProcess()
|
{
|
try
|
{
|
usOutput_tcp = new int[DeviceListBox.Items.Count];
|
return await Task.Run(() =>
|
{
|
GetImage();
|
return usOutput_tcp; // 返回结果
|
}).ConfigureAwait(false);
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"图像处理异常: {ex.Message}");
|
throw; // 重新抛出以触发TCP层的错误处理
|
}
|
}
|
private void TCPServer_Stop_Click(object sender, RoutedEventArgs e)
|
{
|
_tcpServerManager?.Stop();
|
TCPServer_Start.IsEnabled = true;
|
TCPServer_Stop.IsEnabled = false;
|
LinkState.Text = "未连接";
|
LinkState.Foreground = System.Windows.Media.Brushes.Red;
|
}
|
|
private void TCPServer_EnableHeartbeat_Checked(object sender, RoutedEventArgs e)
|
{
|
TCPServer_HeartbeatPanel.Visibility = Visibility.Visible;
|
}
|
|
private void TCPServer_EnableHeartbeat_Unchecked(object sender, RoutedEventArgs e)
|
{
|
TCPServer_HeartbeatPanel.Visibility = Visibility.Collapsed;
|
}
|
|
private void TCPServer_ClearLogs_Click(object sender, RoutedEventArgs e)
|
{
|
Dispatcher.Invoke(() =>
|
TCPServer_LogsTextBox.Clear());
|
}
|
|
|
private void RefreshIpButton_Click(object sender, RoutedEventArgs e)
|
{
|
TCPServer_IpComboBox.Items.Clear();
|
|
// 添加默认选项
|
TCPServer_IpComboBox.Items.Add(new ComboBoxItem
|
{
|
Content = "0.0.0.0 (All Interfaces)"
|
});
|
TCPServer_IpComboBox.Items.Add(new ComboBoxItem
|
{
|
Content = "127.0.0.1 (Loopback)"
|
});
|
|
// 添加实际IP地址
|
foreach (var ip in GetAvailableIPs())
|
{
|
var item = new ComboBoxItem
|
{
|
Content = $"{ip} ({GetNetworkInterfaceName(ip)})",
|
Tag = ip // 存储实际IP对象
|
};
|
TCPServer_IpComboBox.Items.Add(item);
|
}
|
|
TCPServer_IpComboBox.SelectedIndex = 0;
|
}
|
private string GetNetworkInterfaceName(IPAddress ip)
|
{
|
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
|
{
|
foreach (UnicastIPAddressInformation addr in nic.GetIPProperties().UnicastAddresses)
|
{
|
if (addr.Address.Equals(ip))
|
{
|
return nic.Name;
|
}
|
}
|
}
|
return "Unknown";
|
}
|
private List<IPAddress> GetAvailableIPs()
|
{
|
var ips = new List<IPAddress>();
|
|
// 获取所有活动的网络接口
|
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
|
{
|
// 只获取已启用且非虚拟的接口
|
if (nic.OperationalStatus != OperationalStatus.Up ||
|
nic.NetworkInterfaceType == NetworkInterfaceType.Loopback)
|
continue;
|
|
// 获取IPv4地址
|
foreach (UnicastIPAddressInformation ip in nic.GetIPProperties().UnicastAddresses)
|
{
|
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
|
{
|
ips.Add(ip.Address);
|
}
|
}
|
}
|
|
return ips;
|
}
|
/// <summary>
|
/// 获取当前选择的IP地址字符串
|
/// </summary>
|
/// <returns>
|
/// "0.0.0.0" - 所有接口
|
/// "127.0.0.1" - 环回地址
|
/// "192.168.1.100" - 具体IP
|
/// </returns>
|
public string GetSelectedIP()
|
{
|
// 情况1:用户手动输入(IsEditable=true时)
|
if (!string.IsNullOrWhiteSpace(TCPServer_IpComboBox.Text))
|
{
|
if (IsValidIP(TCPServer_IpComboBox.Text))
|
return TCPServer_IpComboBox.Text.Trim();
|
}
|
|
// 情况2:从下拉项选择
|
if (TCPServer_IpComboBox.SelectedItem is ComboBoxItem item)
|
{
|
// 处理特殊选项
|
if (item.Content.ToString().Contains("0.0.0.0"))
|
return "0.0.0.0";
|
if (item.Content.ToString().Contains("127.0.0.1"))
|
return "127.0.0.1";
|
|
// 从内容中提取IP部分(格式:"IP (描述)")
|
var ipPart = item.Content.ToString().Split().FirstOrDefault();
|
if (IsValidIP(ipPart))
|
return ipPart;
|
}
|
|
// 默认返回"0.0.0.0"
|
return "0.0.0.0";
|
}
|
|
// IP地址验证方法
|
private bool IsValidIP(string ipString)
|
{
|
return IPAddress.TryParse(ipString, out _);
|
}
|
/// <summary>
|
/// 安全获取选择的端口号
|
/// </summary>
|
/// <returns>
|
/// 成功返回有效端口(1-65535),失败返回-1并显示错误提示
|
/// </returns>
|
public int GetSelectedPort()
|
{
|
try
|
{
|
// 情况1:从下拉项选择
|
if (TCPServer_PortComboBox.SelectedItem is ComboBoxItem selectedItem)
|
{
|
if (int.TryParse(selectedItem.Content.ToString(), out int port) && IsValidPort(port))
|
return port;
|
}
|
|
// 情况2:手动输入文本
|
if (!string.IsNullOrWhiteSpace(TCPServer_PortComboBox.Text))
|
{
|
if (int.TryParse(TCPServer_PortComboBox.Text, out int manualPort) && IsValidPort(manualPort))
|
return manualPort;
|
}
|
|
throw new ArgumentException("未选择有效端口");
|
}
|
catch (Exception ex)
|
{
|
ShowPortError($"端口获取失败: {ex.Message}");
|
return -1;
|
}
|
}
|
|
// 端口范围验证
|
private bool IsValidPort(int port) => port > 0 && port <= 65535;
|
|
// 错误提示方法
|
private void ShowPortError(string message)
|
{
|
MessageBox.Show(message, "端口配置错误",
|
MessageBoxButton.OK,
|
MessageBoxImage.Error);
|
}
|
#endregion
|
#region 工程方案设置模块按钮事件
|
private void BtnSelectParam_Click(object sender, RoutedEventArgs e)
|
{
|
RefreshDetectionPlanList();
|
if (cmbDetectionPlans.SelectedItem == null)
|
{
|
MessageBox.Show("请先选择检测方案", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
return;
|
}
|
|
string selectedPlan = ((dynamic)cmbDetectionPlans.SelectedItem).FileName;
|
MessageBox.Show($"已选择检测方案: {selectedPlan}", "检测方案确认",
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
}
|
|
/// <summary>
|
/// 加载检测方案列表
|
/// </summary>
|
private void RefreshDetectionPlanList()
|
{
|
var plans = GetAvailableDetectionPlans()
|
.Select(name => new
|
{
|
FileName = name,
|
FullPath = Path.Combine("DetectionPlan", name)
|
}).ToList();
|
|
cmbDetectionPlans.ItemsSource = plans;
|
if (plans.Any()) cmbDetectionPlans.SelectedIndex = 0;
|
}
|
|
/// <summary>
|
/// 获取所有可用检测方案
|
/// </summary>
|
private string[] GetAvailableDetectionPlans()
|
{
|
string planPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DetectionPlan");
|
|
if (!Directory.Exists(planPath))
|
{
|
Directory.CreateDirectory(planPath);
|
return Array.Empty<string>();
|
}
|
|
return Directory.GetFiles(planPath, "*.json")
|
.Select(Path.GetFileName)
|
.ToArray();
|
}
|
|
private void BtnConfirmModel_Click(object sender, RoutedEventArgs e)
|
{
|
if (cmbModels.SelectedItem == null)
|
{
|
MessageBox.Show("请先选择模型文件", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
return;
|
}
|
|
string selectedModel = ((dynamic)cmbModels.SelectedItem).FileName;
|
MessageBox.Show($"已选择模型: {selectedModel}", "模型确认",
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
}
|
/// <summary>
|
/// 加载模型列表
|
/// </summary>
|
private void RefreshModelList()
|
{
|
var models = LBProjService.GetAvailableModels()
|
.Select(name => new
|
{
|
FileName = name,
|
FullPath = Path.Combine("model", name)
|
}).ToList();
|
|
cmbModels.ItemsSource = models;
|
if (models.Any()) cmbModels.SelectedIndex = 0;
|
}
|
|
private void BtnExport_Click(object sender, RoutedEventArgs e)
|
{
|
if (cmbModels.SelectedItem == null)
|
{
|
MessageBox.Show("请先点击【确定】按钮选择模型", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
|
return;
|
}
|
|
// 固定导出路径
|
string projectDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Project");
|
if (!Directory.Exists(projectDir))
|
{
|
Directory.CreateDirectory(projectDir);
|
}
|
|
var saveDialog = new System.Windows.Forms.SaveFileDialog
|
{
|
Title = "导出 LBProj 工程",
|
Filter = "LBProj文件|*.lbproj",
|
FileName = $"project_{DateTime.Now:yyyyMMdd_HHmmss}",
|
InitialDirectory = projectDir
|
};
|
|
if (saveDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
{
|
string modelName = ((dynamic)cmbModels.SelectedItem).FileName;
|
// 使用固定路径的检测方案文件
|
string detectionPlanPath = cmbDetectionPlans.SelectedItem != null ?
|
Path.Combine("DetectionPlan", ((dynamic)cmbDetectionPlans.SelectedItem).FileName) :
|
"";
|
|
var (success, message) = LBProjService.CreateLBProj(
|
detectionPlanPath,
|
modelName,
|
saveDialog.FileName);
|
|
if (success)
|
{
|
Properties.Settings.Default.LastConfigFilePath_Proj = saveDialog.FileName;
|
Properties.Settings.Default.Save();
|
MessageBox.Show($"工程已成功保存到: {saveDialog.FileName}", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
|
OperateLogService.LogOperation("工程文件修改", $"工程文件修改为: {saveDialog.FileName}", null);
|
//txtExportPath.Text = saveDialog.FileName;
|
}
|
else
|
{
|
MessageBox.Show(message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
}
|
}
|
|
private void BtnLoad_Click(object sender, RoutedEventArgs e)
|
{
|
//RefreshProjectList();
|
if (cmbProjects.SelectedItem == null)
|
{
|
MessageBox.Show("请先选择工程文件", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
|
return;
|
}
|
|
string selectedProject = ((dynamic)cmbProjects.SelectedItem).FullPath;
|
var (modelName, configPath, configContent, message) = LBProjService.LoadLBProj(selectedProject);
|
config = JsonConvert.DeserializeObject<ResultJudge.JudgmentConfiguration>(configContent);
|
if (modelName != null)
|
{
|
// 更新模型选择
|
foreach (var item in cmbModels.Items)
|
{
|
if (((dynamic)item).FileName == modelName)
|
{
|
cmbModels.SelectedItem = item;
|
break;
|
}
|
}
|
if (detector != IntPtr.Zero)
|
{
|
DisposeDetector_CPU(detector);
|
}
|
Task.Run(() =>
|
{
|
// 模型推理引擎选择
|
detector = CreateDetector_CPU();
|
bool isLoadModel = InitializeDetector_CPU(detector, Detector_Device, $".\\model\\{modelName}");
|
while (true)
|
{
|
if (isLoadModel)
|
{
|
EnhancedLogViewModel.Instance.AddLog($"模型编译成功");
|
break;
|
}
|
}
|
});
|
Properties.Settings.Default.LastConfigFilePath_Proj = selectedProject;
|
Properties.Settings.Default.Save();
|
//txtParamPath.Text = configPath;
|
//cmbModels.ItemsSource = modelName.ToString();
|
MessageBox.Show($"已加载模型: {modelName}\n{message}", "成功",
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
this.Dispatcher.BeginInvoke(new Action(() =>
|
{
|
ProjectState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
ModelState.Foreground = System.Windows.Media.Brushes.LightGreen;
|
ProjectState.Text = selectedProject;
|
ModelState.Text = modelName;
|
}));
|
EnhancedLogViewModel.Instance.AddLog($"已加载工程文件: {selectedProject},模型:{modelName}");
|
}
|
else
|
{
|
MessageBox.Show(message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
}
|
|
/// <summary>
|
/// 加载工程文件列表
|
/// </summary>
|
private void RefreshProjectList()
|
{
|
var projects = GetAvailableProjects()
|
.Select(name => new
|
{
|
FileName = name,
|
FullPath = Path.Combine("Project", name)
|
}).ToList();
|
|
cmbProjects.ItemsSource = projects;
|
if (projects.Any()) cmbProjects.SelectedIndex = 0;
|
}
|
|
/// <summary>
|
/// 获取所有可用工程文件
|
/// </summary>
|
private string[] GetAvailableProjects()
|
{
|
string projectPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Project");
|
|
if (!Directory.Exists(projectPath))
|
{
|
Directory.CreateDirectory(projectPath);
|
return Array.Empty<string>();
|
}
|
|
return Directory.GetFiles(projectPath, "*.lbproj")
|
.Select(Path.GetFileName)
|
.ToArray();
|
}
|
|
private void BtnRefreshModels_Click(object sender, RoutedEventArgs e)
|
{
|
RefreshModelList();
|
RefreshDetectionPlanList();
|
RefreshProjectList();
|
MessageBox.Show("模型、检测方案和工程文件列表已刷新", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
}
|
#endregion
|
#region 版本说明功能
|
private void VersionButton_Click(object sender, RoutedEventArgs e)
|
{
|
ShowVersionInfo();
|
}
|
|
private void ShowVersionInfo()
|
{
|
try
|
{
|
// 读取版本说明文件
|
string versionFile = "版本说明.txt";
|
if (File.Exists(versionFile))
|
{
|
string versionContent = File.ReadAllText(versionFile);
|
|
// 解析版本说明文件,提取最新版本信息
|
var versionLines = versionContent.Split('\n');
|
string latestVersion = "";
|
string latestDate = "";
|
string latestChanges = "";
|
|
// 从最后一行向前查找最新的版本信息
|
for (int i = versionLines.Length - 1; i >= 0; i--)
|
{
|
if (versionLines[i].Contains("v") && versionLines[i].Contains("."))
|
{
|
// 提取版本日期和版本号
|
var parts = versionLines[i].Trim().Split(' ');
|
foreach (var part in parts)
|
{
|
if (part.Contains(".") && part.Length > 0)
|
{
|
if (part.StartsWith("v") || part.Contains("v"))
|
{
|
latestVersion = part.Trim();
|
}
|
else if (char.IsDigit(part[0]))
|
{
|
latestDate = part.Trim();
|
}
|
}
|
}
|
|
// 查找该版本的更新内容
|
for (int j = i + 1; j < versionLines.Length; j++)
|
{
|
string contentLine = versionLines[j].Trim();
|
|
// 停止条件:空行或新的版本行
|
if (string.IsNullOrEmpty(contentLine) ||
|
(contentLine.Contains("v") && contentLine.Contains(".") && contentLine.Length > 8))
|
{
|
break;
|
}
|
|
// 添加所有非空内容行
|
if (contentLine.Length > 0)
|
{
|
latestChanges += contentLine + "\n";
|
}
|
|
// 最多读取8行内容
|
if (j - i > 8)
|
{
|
break;
|
}
|
}
|
|
// 显示版本信息对话框
|
string message = $"当前软件版本: {latestVersion}\n" +
|
$"发布日期: {latestDate}\n\n" +
|
$"最新更新内容:\n{latestChanges}\n" +
|
$"完整版本历史记录请查看版本说明.txt文件";
|
|
MessageBox.Show(message, "软件版本说明", MessageBoxButton.OK, MessageBoxImage.Information);
|
return;
|
}
|
}
|
|
// 如果没有找到版本信息,显示默认提示
|
MessageBox.Show("版本说明文件中未找到有效的版本信息", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
}
|
else
|
{
|
MessageBox.Show("版本说明文件不存在", "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
|
}
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show($"读取版本信息时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
}
|
}
|
#endregion
|
}
|
}
|