using HalconDotNet;
|
using LB_SmartVision.Forms;
|
using LB_SmartVision.Forms.Pages;
|
using LB_SmartVision.Forms.Pages.BarcodeReaderPage;
|
using LB_SmartVision.Forms.Pages.CameraPage;
|
using LB_SmartVision.Forms.Pages.CommunicatorPage;
|
using LB_SmartVision.Forms.Pages.HistoricalData;
|
using LB_SmartVision.Forms.Pages.LEDLightSourceControlPage;
|
using LB_SmartVision.Forms.Pages.MESPage;
|
using LB_SmartVision.Forms.Pages.MotionControlPage;
|
using LB_SmartVision.Forms.Pages.ProcessPage;
|
using LB_SmartVision.Forms.Pages.SettingPage;
|
using LB_SmartVision.Forms.Pages.UserManagementPage;
|
using LB_SmartVision.ProcessRun;
|
using LB_SmartVision.SQL;
|
using LB_SmartVision.Tool;
|
using LB_SmartVisionCameraDevice.PHM6000;
|
using LB_SmartVisionCommon;
|
using LB_SmartVisionLoginUI;
|
using LB_VisionProcesses;
|
using LB_VisionProcesses.BarcodeReaders;
|
using LB_VisionProcesses.BarcodeReaders.Huayray;
|
using LB_VisionProcesses.Cameras;
|
using LB_VisionProcesses.Cameras.HikCameras;
|
using LB_VisionProcesses.Cameras.HRCameras;
|
using LB_VisionProcesses.Cameras.LBCameras;
|
using LB_VisionProcesses.Cameras.LocalCameras;
|
using LB_VisionProcesses.Cameras.MicroCameras;
|
using LB_VisionProcesses.Cameras.MindCameras;
|
using LB_VisionProcesses.Communicators;
|
using LB_VisionProcesses.Communicators.SiemensS7;
|
using LB_VisionProcesses.Communicators.Tcom;
|
using LB_VisionProcesses.Forms;
|
using log4net.Config;
|
using Newtonsoft.Json;
|
using Newtonsoft.Json.Serialization;
|
using Serilog;
|
using Serilog.Events;
|
using Sunny.UI;
|
using System;
|
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Data;
|
using System.Diagnostics;
|
using System.Drawing;
|
using System.Linq;
|
using System.Reflection;
|
using System.Text;
|
using System.Text.RegularExpressions;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
|
namespace LB_SmartVision
|
{
|
public partial class VisionForm : Form
|
{
|
#region Variable
|
public string NowBom = string.Empty;
|
|
AllProcessesPage AllProcessesPage = new AllProcessesPage();
|
CamerasEditPage CamerasEditPage = new CamerasEditPage();
|
BarcodeReadersEditPage BarcodeReadersEditPage = new BarcodeReadersEditPage();
|
HistoricalDataEditPage HistoricalDataEditPage = new HistoricalDataEditPage();
|
CommunicatorsEditPage CommunicatorsEditPage = new CommunicatorsEditPage();
|
SettingEditPage SettingEditPage = new SettingEditPage();
|
MESEditPage MESEditPage = new MESEditPage();
|
MotionControlEditPage MotionControlEditPage = new MotionControlEditPage();
|
UserManagementEditPage UserManagementEditPage = new UserManagementEditPage();
|
|
LEDLightSourceControlEditPage lEDLightSourceControlEditPage = new LEDLightSourceControlEditPage();
|
|
byte[] Assembly_LB_VisionProcessesBytes = File.ReadAllBytes("LB_VisionProcesses.dll");
|
/// <summary>
|
/// 用于反序列化的程序集引用
|
/// </summary>
|
Assembly Assembly_LB_VisionProcessesDll = null;
|
|
//string LogFilePath(string LogEvent) => $"{GlobalVar.strPathLog}\\{LogEvent}.log";
|
//string SerilogOutputTemplate = "{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + new string('-', 50);
|
|
|
// 窗体类的全局变量:标记是否允许切换Tab(默认允许)
|
private bool _isTabSwitchAllowed = true;
|
|
#endregion
|
|
public VisionForm()
|
{
|
InitializeComponent();
|
HOperatorSet.SetWindowAttr("background_color", "gray");
|
Assembly_LB_VisionProcessesDll = Assembly.Load(Assembly_LB_VisionProcessesBytes);
|
|
GlobalVar.dicCommunicators.DictionaryChanged += CommunicatorsChanged;
|
GlobalVar.dicCameras.DictionaryChanged += CamerasChanged;
|
GlobalVar.dicProcesses.DictionaryChanged += ProcessRunBllChanged;
|
|
//最开始就清空所有Tab页
|
materialTabControl.TabPages.Clear();
|
AllProcessesPage.controlsPanel.Dock = DockStyle.Fill;
|
materialTabControl.Controls.Add(AllProcessesPage);
|
|
HistoricalDataEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(HistoricalDataEditPage));
|
|
lEDLightSourceControlEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(lEDLightSourceControlEditPage));
|
|
CamerasEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(CamerasEditPage));
|
|
BarcodeReadersEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(BarcodeReadersEditPage));
|
|
CommunicatorsEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(CommunicatorsEditPage));
|
|
SettingEditPage.LogInfo += LogInfo;
|
SettingEditPage.OnRemoveSettingPage += SettingEditPage_OnRemoveSettingPage;
|
materialTabControl.Controls.Add(new MyPage(SettingEditPage));
|
|
MESEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(MESEditPage));
|
|
MotionControlEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(MotionControlEditPage));
|
|
UserManagementEditPage.LogInfo += LogInfo;
|
materialTabControl.Controls.Add(new MyPage(UserManagementEditPage));
|
for (int i = 0; i < materialTabControl.TabPages.Count; i++)
|
{
|
materialTabControl.TabPages[i].Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
|
materialTabControl.TabPages[i].ForeColor = Color.White;
|
}
|
materialTabSelector.BaseTabControl = materialTabControl;
|
//materialTabSelector.Font = new Font("Microsoft YaHei UI", 18F, FontStyle.Regular, GraphicsUnit.Point, 0);
|
|
//Log.Logger = new LoggerConfiguration()
|
// .MinimumLevel.Debug() // 所有Sink的最小记录级别
|
// .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.File(LogFilePath("Log"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
|
// .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(LogFilePath("Log"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
|
// .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(LogFilePath("Log"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
|
// .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(LogFilePath("Error"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
|
// .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Fatal).WriteTo.File(LogFilePath("Log"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
|
// .CreateLogger();
|
|
// 初始化下拉框(假设已放置并正确命名为 materialCombobox1)
|
//materialCombobox1.Visible = false; // 默认隐藏
|
materialCombobox1.SelectedIndexChanged += MaterialCombobox1_SelectedIndexChanged;
|
|
// 监听 TabControl 的变化
|
materialTabControl.ControlAdded += (s, e) => UpdateOverflowComboBox();
|
materialTabControl.ControlRemoved += (s, e) => UpdateOverflowComboBox();
|
|
//HOperatorSet.SetSystem("max_mem_cache", 2048);
|
}
|
|
string removeName = string.Empty;
|
private void SettingEditPage_OnRemoveSettingPage(string name)
|
{
|
removeName = name;
|
if (materialCombobox1.Items.Contains(removeName))
|
{
|
materialCombobox1.Items.Remove(removeName);
|
materialCombobox1.SelectedItem = materialTabControl.SelectedTab.Text;
|
}
|
}
|
|
private int CalculateTotalTabWidth()
|
{
|
// 简单估算:每个选项卡宽度 = 文本宽度 + 内边距(可根据实际调整)
|
int total = 0;
|
using (Graphics g = materialTabControl.CreateGraphics())
|
{
|
foreach (TabPage page in materialTabControl.TabPages)
|
{
|
SizeF textSize = g.MeasureString(page.Text, materialTabControl.Font);
|
total += (int)textSize.Width + 32; // 32 为左右内边距估计值
|
}
|
}
|
return total;
|
}
|
private void UpdateOverflowComboBox()
|
{
|
// 判断是否溢出的逻辑(参考上一轮回复中的 CalculateTotalTabWidth 方法)
|
bool overflow = CalculateTotalTabWidth() > materialTabControl.Width;
|
|
//materialCombobox1.Visible = overflow;
|
|
//if (overflow)
|
//{
|
// materialCombobox1.Items.Clear();
|
// foreach (TabPage page in materialTabControl.TabPages)
|
// {
|
// // 使用正确的控件,添加项的方式不变
|
// materialCombobox1.Items.Add(page.Text);
|
// }
|
// // 可选:默认选中当前项
|
// materialCombobox1.SelectedItem = materialTabControl.SelectedTab.Text;
|
//}
|
|
materialCombobox1.Items.Clear();
|
foreach (TabPage page in materialTabControl.TabPages)
|
{
|
// 使用正确的控件,添加项的方式不变
|
if (/*!string.IsNullOrEmpty(removeName) && */!removeName.Equals(page.Text))
|
{
|
materialCombobox1.Items.Add(page.Text);
|
}
|
}
|
// 可选:默认选中当前项
|
materialCombobox1.SelectedItem = materialTabControl.SelectedTab.Text;
|
|
}
|
|
private void MaterialCombobox1_SelectedIndexChanged(object sender, EventArgs e)
|
{
|
if (materialCombobox1.SelectedItem != null)
|
{
|
string selectedText = materialCombobox1.SelectedItem.ToString();
|
// 查找并切换选项卡
|
foreach (TabPage page in materialTabControl.TabPages)
|
{
|
if (page.Text == selectedText)
|
{
|
materialTabControl.SelectedTab = page;
|
break;
|
}
|
}
|
}
|
}
|
|
|
private void ProcessRunBllChanged(object? sender, DictionaryChangedEventArgs<string, ProcessRunBll> e)
|
{
|
try
|
{
|
string msg = string.Empty;
|
List<MyPage> removeMyPage = new List<MyPage>();
|
switch (e.ChangeType)
|
{
|
case DictionaryChangeType.Added:
|
{
|
string AddProcessName = e.NewKey;
|
GlobalVar.dicProcesses[AddProcessName].LogInfo += LogInfo;
|
if (GlobalVar.dicProcesses[AddProcessName].Load(out msg))
|
{
|
LogInfo($"流程[{AddProcessName}]加载成功", LogInfoType.PASS);
|
IProcess.dicGlobalVars.TryAdd($"{AddProcessName}.Result", false);
|
IProcess.dicGlobalVars.TryAdd($"{AddProcessName}.Msg", "");
|
|
ProcessRunBll processRunBll = GlobalVar.dicProcesses[AddProcessName];
|
ProcessPage ProcessPage = new ProcessPage(processRunBll.Name, processRunBll);
|
ProcessPage.LogInfo += LogInfo;
|
if (materialTabControl.InvokeRequired)
|
{
|
materialTabControl.Invoke(new Action(() =>
|
{
|
materialTabControl.Controls.Add(new MyPage(ProcessPage));
|
}));
|
}
|
else
|
{
|
materialTabControl.Controls.Add(new MyPage(ProcessPage));
|
}
|
}
|
else
|
{
|
LogInfo($"流程[{AddProcessName}]加载失败,原因是{msg}", LogInfoType.ERROR);
|
}
|
LogInfo($"添加流程[{AddProcessName}]", LogInfoType.INFO);
|
break;
|
}
|
case DictionaryChangeType.Removed:
|
{
|
string RemoveProcessName = e.OldKey;
|
foreach (var control in materialTabControl.Controls)
|
{
|
if (control != null && control is MyPage && ((MyPage)control).UserControl is ProcessPage processPage)
|
{
|
if (processPage.Text == RemoveProcessName)
|
{
|
IProcess.dicGlobalVars.TryRemove($"{RemoveProcessName}.Result", out _);
|
IProcess.dicGlobalVars.TryRemove($"{RemoveProcessName}.Msg", out _);
|
processPage.LogInfo -= LogInfo;
|
removeMyPage.Add((MyPage)control);
|
}
|
}
|
}
|
|
foreach (var myPage in removeMyPage)
|
{
|
if (materialTabControl.InvokeRequired)
|
{
|
materialTabControl.Invoke(new Action(() =>
|
{
|
materialTabControl.Controls.Remove(myPage);
|
}));
|
}
|
else
|
{
|
materialTabControl.Controls.Remove(myPage);
|
}
|
}
|
|
LogInfo($"移除流程[{RemoveProcessName}]", LogInfoType.INFO);
|
break;
|
}
|
case DictionaryChangeType.Renamed:
|
{
|
string OldProcessName = e.OldKey;
|
string NewProcessName = e.NewKey;
|
try
|
{
|
IProcess.dicGlobalVars.TryRemove($"{OldProcessName}.Result", out object obj1);
|
IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Result", obj1);
|
|
IProcess.dicGlobalVars.TryRemove($"{OldProcessName}.Msg", out object obj2);
|
IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Msg", obj2);
|
}
|
catch { }
|
|
LB_SmartVision.Tool.Tool.RenameDirectory(GlobalVar.allProcessPath + "\\" + OldProcessName
|
, GlobalVar.allProcessPath + "\\" + NewProcessName);
|
e.NewValue.Name = NewProcessName;
|
|
foreach (var control in materialTabControl.Controls)
|
{
|
if (control != null && control is MyPage && ((MyPage)control).UserControl is ProcessPage)
|
{
|
ProcessPage processPage = ((MyPage)control).UserControl as ProcessPage;
|
if (processPage.Text == OldProcessName)
|
{
|
if (materialTabControl.InvokeRequired)
|
{
|
materialTabControl.Invoke(new Action(() =>
|
{
|
materialTabControl.Controls.Remove((MyPage)control);
|
}));
|
}
|
else
|
{
|
materialTabControl.Controls.Remove((MyPage)control);
|
}
|
|
|
if (GlobalVar.dicProcesses[NewProcessName].Load(out msg))
|
{
|
LogInfo($"流程[{NewProcessName}]重命名后加载成功", LogInfoType.PASS);
|
|
IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Result", false);
|
IProcess.dicGlobalVars.TryAdd($"{NewProcessName}.Msg", "");
|
|
ProcessRunBll processRunBll = GlobalVar.dicProcesses[NewProcessName];
|
ProcessPage ProcessPage = new ProcessPage(processRunBll.Name, processRunBll);
|
ProcessPage.LogInfo += LogInfo;
|
if (materialTabControl.InvokeRequired)
|
{
|
materialTabControl.Invoke(new Action(() =>
|
{
|
materialTabControl.Controls.Add(new MyPage(ProcessPage));
|
}));
|
}
|
else
|
{
|
materialTabControl.Controls.Add(new MyPage(ProcessPage));
|
}
|
}
|
else
|
{
|
LogInfo($"流程[{NewProcessName}]重命名后加载失败,原因是{msg}", LogInfoType.ERROR);
|
}
|
}
|
}
|
}
|
|
LogInfo(string.Format("重命名流程名[{0}]修改为[{1}]", OldProcessName, NewProcessName), LogInfoType.INFO);
|
break;
|
}
|
}
|
}
|
catch { }
|
|
}
|
|
private void CommunicatorsChanged(object? sender, DictionaryChangedEventArgs<string, BaseCommunicator> e)
|
{
|
try
|
{
|
switch (e.ChangeType)
|
{
|
case DictionaryChangeType.Added:
|
{
|
e.NewValue.TriggerRunMessageReceived += TriggerRunMessageReceived;
|
LogInfo($"通讯口[{e.NewValue.CommunicatorName}]加载触发通讯", LogInfoType.INFO);
|
e.NewValue.CommunicatorName = e.NewKey;
|
break;
|
}
|
case DictionaryChangeType.Renamed:
|
{
|
string OldCommunicatorName = e.OldKey;
|
string NewCommunicatorName = e.NewKey;
|
LogInfo(string.Format("重命名通讯口名[{0}]修改为[{1}]", OldCommunicatorName, NewCommunicatorName), LogInfoType.INFO);
|
e.NewValue.CommunicatorName = NewCommunicatorName;
|
break;
|
}
|
case DictionaryChangeType.Removed:
|
{
|
if (e.OldValue != null && e.OldValue is BaseCommunicator)
|
{
|
e.OldValue.Disconnect();
|
}
|
e.OldValue.TriggerRunMessageReceived -= TriggerRunMessageReceived;
|
LogInfo($"通讯口[{e.OldValue.CommunicatorName}]移除触发通讯", LogInfoType.INFO);
|
break;
|
}
|
}
|
}
|
catch { }
|
}
|
|
private void LogInfo(string strLog, LogInfoType infoType)
|
{
|
if (string.IsNullOrEmpty(strLog))
|
{
|
return;
|
}
|
string strInfo = DateTime.Now.ToString("[yyyy:MM:dd:HH:mm:ss:fff] ");
|
strInfo += strLog;
|
if (infoType != LogInfoType.NOSHOW)
|
{
|
// 如果当前不是 UI 线程,则通过 Invoke 将操作调度到 UI 线程
|
if (this.rich_Info.InvokeRequired)
|
{
|
this.rich_Info.BeginInvoke(new Action<string>((msg) =>
|
{
|
if (this.rich_Info.Lines.Length > 1000)
|
{
|
this.rich_Info.Clear();
|
}
|
switch (infoType)
|
{
|
case LogInfoType.INFO:
|
{
|
this.rich_Info.SelectionColor = Color.Wheat;
|
AsyncLogHelper.Info(strLog);
|
break;
|
}
|
case LogInfoType.WARN:
|
{
|
this.rich_Info.SelectionColor = Color.Yellow;
|
AsyncLogHelper.Warn(strLog);
|
break;
|
}
|
case LogInfoType.PASS:
|
{
|
this.rich_Info.SelectionColor = Color.Green;
|
AsyncLogHelper.Info(strLog);
|
break;
|
}
|
case LogInfoType.ERROR:
|
{
|
this.rich_Info.SelectionColor = Color.Red;
|
AsyncLogHelper.Error(strLog);
|
break;
|
}
|
}
|
// 更新 UI 控件,比如显示接收到的消息
|
this.rich_Info.AppendText(strInfo);
|
this.rich_Info.AppendText("\r\n");
|
this.rich_Info.SelectionStart = this.rich_Info.Text.Length;
|
this.rich_Info.ScrollToCaret();
|
}), strInfo);
|
}
|
else
|
{
|
|
if (this.rich_Info.Lines.Length > 500)
|
{
|
this.rich_Info.Clear();
|
}
|
// 如果已经在 UI 线程上,直接更新 UI
|
switch (infoType)
|
{
|
case LogInfoType.INFO:
|
{
|
this.rich_Info.SelectionColor = Color.Wheat;
|
AsyncLogHelper.Info(strLog);
|
break;
|
}
|
case LogInfoType.WARN:
|
{
|
this.rich_Info.SelectionColor = Color.Yellow;
|
AsyncLogHelper.Warn(strLog);
|
break;
|
}
|
case LogInfoType.PASS:
|
{
|
this.rich_Info.SelectionColor = Color.Green;
|
AsyncLogHelper.Info(strLog);
|
break;
|
}
|
case LogInfoType.ERROR:
|
{
|
this.rich_Info.SelectionColor = Color.Red;
|
AsyncLogHelper.Error(strLog);
|
break;
|
}
|
}
|
this.rich_Info.AppendText(strInfo);
|
this.rich_Info.AppendText("\r\n");
|
this.rich_Info.SelectionStart = this.rich_Info.Text.Length;
|
this.rich_Info.ScrollToCaret();
|
}
|
}
|
}
|
|
public static bool SaveAllLayout()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.dicLayout, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allLayoutPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch { }
|
}
|
|
File.WriteAllText(GlobalVar.allLayoutPath, strJson, Encoding.UTF8);
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public static bool LoadAllCsv(string allCsvPath)
|
{
|
try
|
{
|
if (!File.Exists(allCsvPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allCsvPath);
|
SaveAllCsv();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allCsvPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
|
GlobalVar.dicCsvSetting.Clear();
|
GlobalVar.dicCsvSetting = JsonConvert.DeserializeObject<ConcurrentDictionary<string, CsvSetting>>(strJson);
|
if (GlobalVar.dicCsvSetting == null)
|
{
|
GlobalVar.dicCsvSetting = new ConcurrentDictionary<string, CsvSetting>();
|
return false;
|
}
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public static bool SaveAllCsv()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.dicCsvSetting, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allCsvPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch { }
|
}
|
|
File.WriteAllText(GlobalVar.allCsvPath, strJson, Encoding.UTF8);
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool LoadAllProcessSetting(string allProcessSettingStringPath)
|
{
|
try
|
{
|
if (!File.Exists(allProcessSettingStringPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allProcessSettingStringPath);
|
SaveAllProcessSetting();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allProcessSettingStringPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
|
GlobalVar.dicProcessSetting = JsonConvert.DeserializeObject<ConcurrentDictionary<int, ConcurrentDictionary<string, string>>>(strJson);
|
|
if (GlobalVar.dicProcessSetting == null)
|
{
|
GlobalVar.dicProcessSetting = new ConcurrentDictionary<int, ConcurrentDictionary<string, string>>();
|
}
|
|
try
|
{
|
string json = File.ReadAllText(GlobalVar.allRunSettingStringPath);
|
var settings = new JsonSerializerSettings
|
{
|
TypeNameHandling = TypeNameHandling.Auto // 处理多态类型
|
};
|
|
GlobalVar.ControlStates = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);
|
}
|
catch { }
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public static bool SaveAllProcessSetting()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.dicProcessSetting, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allProcessSettingStringPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch { }
|
}
|
File.WriteAllText(GlobalVar.allProcessSettingStringPath, strJson, Encoding.UTF8);
|
//LogInfo($"流程设置保存成功", LogInfoType.INFO);
|
return true;
|
}
|
catch { return false; }
|
}
|
private void EnsureDirectory(string path)
|
{
|
// 如果是相对路径,转换为绝对路径
|
string fullPath = Path.IsPathRooted(path) ? path : Path.GetFullPath(path);
|
|
if (!Directory.Exists(fullPath))
|
{
|
Directory.CreateDirectory(fullPath);
|
LogInfo($"✅ 目录创建: {fullPath}", LogInfoType.INFO);
|
}
|
else
|
{
|
LogInfo($"ℹ️ 目录已存在: {fullPath}", LogInfoType.INFO);
|
}
|
}
|
|
private void CamerasChanged(object sender, DictionaryChangedEventArgs<string, BaseCamera> e)
|
{
|
try
|
{
|
switch (e.ChangeType)
|
{
|
case DictionaryChangeType.Added:
|
{
|
e.NewValue.TriggerRunMessageReceived += TriggerRunMessageReceived;
|
LogInfo($"相机[{e.NewValue.SN}]加载触发通讯", LogInfoType.INFO);
|
e.NewValue.SN = e.NewKey;
|
break;
|
}
|
case DictionaryChangeType.Removed:
|
{
|
if (e.OldValue != null && e.OldValue is BaseCommunicator)
|
{
|
e.OldValue.CloseDevice();
|
}
|
e.OldValue.TriggerRunMessageReceived -= TriggerRunMessageReceived;
|
LogInfo($"相机[{e.OldValue.SN}]移除触发通讯", LogInfoType.INFO);
|
break;
|
}
|
}
|
}
|
catch { }
|
}
|
|
private void VisionForm_Load(object sender, EventArgs e)
|
{
|
XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config"));
|
string[] paths = {
|
@"Log\Run",
|
@"Log\Debug",
|
@"Log\Error",
|
@"Log\Fatal",
|
@"Log\Warn",
|
};
|
foreach (string path in paths)
|
{
|
EnsureDirectory(path);
|
}
|
if (!LB_SmartVision.Tool.Tool.ReadStringConfig("数据库名称", out string DateBaseName))
|
{
|
DateBaseName = "Product0";
|
LB_SmartVision.Tool.Tool.WriteConfig("数据库名称", DateBaseName);
|
LB_SmartVision.Tool.Tool.WriteConfig("产品列表", DateBaseName);
|
}
|
LB_SmartVision.Tool.Tool.ReadStringConfig("User ID", out string User_ID);
|
LB_SmartVision.Tool.Tool.ReadStringConfig("Password", out string Password);
|
GlobalVar.strProductName = DateBaseName;
|
//加载LB相机参数
|
if (LoadAllLBCameras(GlobalVar.allCamerasLBPath))
|
{
|
LogInfo("LB3D相机配置文件加载成功!", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("LB3D相机配置文件加载失败", LogInfoType.ERROR);
|
}
|
//加载通讯
|
foreach (BaseCommunicator com in GlobalVar.dicCommunicators.Values)
|
{
|
com.Disconnect();
|
}
|
GlobalVar.dicCommunicators.Clear();
|
if (LoadAllCommunicators(GlobalVar.allCommunicatorsConnectionStringPath))
|
{
|
LogInfo("通讯加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("通讯加载失败", LogInfoType.ERROR);
|
}
|
//加载相机
|
foreach (BaseCamera camera in GlobalVar.dicCameras.Values)
|
{
|
camera.Dispose();
|
}
|
GlobalVar.dicCameras.Clear();
|
if (LoadAllCameras(GlobalVar.allCamerasConnectionStringPath))
|
{
|
LogInfo("相机加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("相机加载失败", LogInfoType.ERROR);
|
}
|
//加载读码器
|
foreach (var reader in GlobalVar.dicBarcodeReaders.Values)
|
{
|
reader.Dispose();
|
}
|
GlobalVar.dicBarcodeReaders.Clear();
|
if (LoadAllBarcodeReaders(GlobalVar.allBarcodeReadersConnectionStringPath))
|
{
|
LogInfo("读码器加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("读码器加载失败", LogInfoType.ERROR);
|
}
|
//加载全局变量
|
IProcess.dicGlobalVars.Clear();
|
if (LoadAllProcessVars(GlobalVar.allProcessVarsPath))
|
{
|
LogInfo("全局变量加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("全局变量加载失败", LogInfoType.ERROR);
|
}
|
//加载运行控制参数配置
|
GlobalVar.dicMotionControlData.Clear();
|
if (LoadMotionControlDatas(GlobalVar.allMotionControlDataPath))
|
{
|
LogInfo("运动控制参数加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("运ca动控制参数加载失败", LogInfoType.ERROR);
|
}
|
//加载LED光源控制器参数配置
|
GlobalVar.dicSerialPort.Clear();
|
if (LoadSerialPorts(GlobalVar.AllSerialPortPath))
|
{
|
LogInfo("光源控制加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("光源控制参数加载失败", LogInfoType.ERROR);
|
}
|
//加载流程
|
GlobalVar.dicProcesses.Clear();
|
if (LoadAllProcess(GlobalVar.allProcessConnectionStringPath))
|
{
|
LogInfo("流程加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("流程加载失败", LogInfoType.ERROR);
|
}
|
//加载触发设置
|
if (LoadAllProcessSetting(GlobalVar.allProcessSettingStringPath))
|
{
|
LogInfo("流程设置加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("流程设置加载失败", LogInfoType.ERROR);
|
}
|
|
//加载流程布局
|
GlobalVar.dicLayout.Clear();
|
if (LoadAllLayout(GlobalVar.allLayoutPath))
|
{
|
LogInfo("流程布局加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("流程布局加载失败", LogInfoType.ERROR);
|
}
|
|
//加载流程表格
|
GlobalVar.dicCsvSetting.Clear();
|
if (LoadAllCsv(GlobalVar.allCsvPath))
|
{
|
LogInfo("流程表格加载成功", LogInfoType.PASS);
|
}
|
else
|
{
|
LogInfo("流程表格加载失败", LogInfoType.ERROR);
|
}
|
|
//发送LED串口通讯
|
#region 发送LED串口通讯
|
|
if (GlobalVar.dicSerialPort != null && GlobalVar.dicSerialPort.Count > 0)
|
{
|
LEDControlSerialPort lEDControlSerialPort = new LEDControlSerialPort();
|
foreach (var item in GlobalVar.dicSerialPort.Keys)
|
{
|
lEDControlSerialPort.LEDControlParams = GlobalVar.dicSerialPort[item];
|
lEDControlSerialPort.OpenPort();
|
if (lEDControlSerialPort.serialPort.IsOpen)
|
{
|
foreach (var itemCH in GlobalVar.dicSerialPort[item].SendData.Keys)
|
{
|
switch (itemCH)
|
{
|
case "CH1":
|
{
|
lEDControlSerialPort.serialPort.Write(GlobalVar.dicSerialPort[item].SendData[itemCH]);
|
break;
|
}
|
case "CH2":
|
{
|
lEDControlSerialPort.serialPort.Write(GlobalVar.dicSerialPort[item].SendData[itemCH]);
|
break;
|
}
|
case "CH3":
|
{
|
lEDControlSerialPort.serialPort.Write(GlobalVar.dicSerialPort[item].SendData[itemCH]);
|
break;
|
}
|
case "CH4":
|
{
|
lEDControlSerialPort.serialPort.Write(GlobalVar.dicSerialPort[item].SendData[itemCH]);
|
break;
|
}
|
default:
|
{
|
break;
|
}
|
}
|
Thread.Sleep(50);
|
}
|
}
|
lEDControlSerialPort.ClosePort();
|
Thread.Sleep(100);
|
}
|
}
|
|
#endregion
|
|
//发送运动控制参数
|
#region 发送运动控制参数
|
|
if (GlobalVar.dicMotionControlData != null && GlobalVar.dicMotionControlData.Count > 0 && GlobalVar.dicMotionControlData.ContainsKey(GlobalVar.strProductName))
|
{
|
foreach (var item in GlobalVar.dicMotionControlData[GlobalVar.strProductName].Keys)
|
{
|
if (GlobalVar.dicCommunicators.Keys.Contains("通讯0"))
|
{
|
SiemensLBS7 siemensLBS7 = GlobalVar.dicCommunicators["通讯0"] as SiemensLBS7;
|
siemensLBS7.Write(GlobalVar.dicMotionControlData[GlobalVar.strProductName][item].XAxisAddress, GlobalVar.dicMotionControlData[GlobalVar.strProductName][item].XAxisAddress);
|
}
|
}
|
}
|
|
#endregion
|
|
//显示所有产品
|
cmbProduct.Items.Clear();
|
LB_SmartVision.Tool.Tool.ReadStringConfig("产品列表", out string Products);
|
List<string> lstProduct = (Products.Split(',')).ToList();
|
foreach (string DatabaseName in lstProduct)
|
{
|
cmbProduct.Items.Add(DatabaseName);
|
}
|
cmbProduct.Items.Add("编辑");
|
cmbProduct.Text = GlobalVar.strProductName;
|
this.WindowState = FormWindowState.Maximized;
|
DatabaseRecordProductDataHelper.InitializeDatabase();
|
}
|
|
public void SaveAllSetting()
|
{
|
SaveAllProcess();
|
SaveAllProcessVars();
|
SaveAllCommunicators();
|
SaveAllCameras();
|
SaveAllProcessSetting();
|
SaveAllLayout();
|
SaveAllCsv();
|
SaveMotionControlDatas();
|
SaveSerialPorts();
|
SaveAllBarcodeReaders();
|
}
|
|
|
public bool LoadAllBarcodeReaders(string allBarcodeReadersConnectionStringPath)
|
{
|
if (!File.Exists(allBarcodeReadersConnectionStringPath))
|
{
|
Debug.WriteLine("读码器配置文件不存在,创建空文件");
|
SaveAllBarcodeReaders();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allBarcodeReadersConnectionStringPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
GlobalVar.allBarcodeReadersConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson);
|
if (GlobalVar.allBarcodeReadersConnectionString == null)
|
{
|
MessageBox.Show("读码器加载失败!", "异常");
|
return false;
|
}
|
BarcodeReaderBase reader = null;
|
foreach (var ReaderConnectionString in GlobalVar.allBarcodeReadersConnectionString)
|
{
|
Enum.TryParse<BarcodeReaderBrand>(ReaderConnectionString.Value, out BarcodeReaderBrand brand);
|
switch (brand)
|
{
|
case BarcodeReaderBrand.Huayray:
|
{
|
reader = new HRBarcodeReader();
|
break;
|
}
|
default:
|
{
|
MessageBox.Show($"[{ReaderConnectionString.Key}]读码器品牌不支持!", "异常");
|
continue;
|
}
|
}
|
reader.SN = ReaderConnectionString.Key;
|
if (!reader.Open(ReaderConnectionString.Key))
|
{
|
LogInfo($"初始化读码器[{ReaderConnectionString.Key}]失败", LogInfoType.ERROR);
|
reader.IsConnected = false;
|
reader.IsGrabbing = false;
|
}
|
else
|
{
|
LogInfo($"初始化读码器[{ReaderConnectionString.Key}]成功", LogInfoType.PASS);
|
}
|
|
GlobalVar.dicBarcodeReaders.TryAdd(ReaderConnectionString.Key, reader);
|
}
|
|
return true;
|
}
|
|
public bool SaveAllBarcodeReaders()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
GlobalVar.allBarcodeReadersConnectionString = new ConcurrentDictionary<string, string>();
|
|
foreach (var item in GlobalVar.dicBarcodeReaders)
|
{
|
string ReaderSN = item.Value.SN;
|
string ReaderBrand = item.Value.Brand.ToString();
|
|
if (string.IsNullOrEmpty(ReaderSN) || string.IsNullOrEmpty(ReaderBrand))
|
{
|
break;
|
}
|
GlobalVar.allBarcodeReadersConnectionString.TryAdd(ReaderSN, ReaderBrand);
|
}
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.allBarcodeReadersConnectionString, settings);
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allBarcodeReadersConnectionStringPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch (Exception)
|
{ }
|
}
|
File.WriteAllText(GlobalVar.allBarcodeReadersConnectionStringPath, strJson, Encoding.UTF8);
|
return true;
|
}
|
catch { return false; }
|
}
|
|
|
public bool LoadSerialPorts(string allSerialPortPath)
|
{
|
try
|
{
|
GlobalVar.dicSerialPort = ConfigManager<Dictionary<string, LEDControlParams>>.LoadConfig<Dictionary<string, LEDControlParams>>(allSerialPortPath);
|
}
|
catch
|
{
|
return false;
|
}
|
return true;
|
}
|
public bool SaveSerialPorts()
|
{
|
try
|
{
|
ConfigManager<Dictionary<string, LEDControlParams>>.SaveConfig<Dictionary<string, LEDControlParams>>(GlobalVar.dicSerialPort, GlobalVar.AllSerialPortPath);
|
}
|
catch
|
{
|
return false;
|
}
|
return true;
|
}
|
public bool LoadMotionControlDatas(string alMotionControlDataPath)
|
{
|
try
|
{
|
GlobalVar.dicMotionControlData = ConfigManager<Dictionary<string, Dictionary<string, RecordMotionControlData>>>.LoadConfig<Dictionary<string, Dictionary<string, RecordMotionControlData>>>(alMotionControlDataPath);
|
}
|
catch
|
{
|
return false;
|
}
|
return true;
|
}
|
|
public bool SaveMotionControlDatas()
|
{
|
try
|
{
|
Dictionary<string, List<string>> removeCameraSN = new Dictionary<string, List<string>>();
|
foreach (var item in GlobalVar.dicMotionControlData.Keys)
|
{
|
List<string> list = new List<string>();
|
foreach (var itemSN in GlobalVar.dicMotionControlData[item].Keys)
|
{
|
if (!GlobalVar.dicCameras.Keys.Contains(itemSN))
|
{
|
list.Add(itemSN);
|
}
|
}
|
if (list.Count > 0)
|
{
|
removeCameraSN.TryAdd(item, list);
|
}
|
}
|
foreach (var item in removeCameraSN.Keys)
|
{
|
foreach (var itemSN in removeCameraSN[item])
|
{
|
//GlobalVar.dicMotionControlData[item].
|
GlobalVar.dicMotionControlData[item].Remove(itemSN);
|
}
|
}
|
ConfigManager<Dictionary<string, Dictionary<string, RecordMotionControlData>>>.SaveConfig<Dictionary<string, Dictionary<string, RecordMotionControlData>>>(GlobalVar.dicMotionControlData, GlobalVar.allMotionControlDataPath);
|
}
|
catch
|
{
|
return false;
|
}
|
return true;
|
}
|
|
public bool LoadAllCameras(string allCamerasConnectionStringPath)
|
{
|
if (!File.Exists(allCamerasConnectionStringPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allCamerasConnectionStringPath);
|
SaveAllCameras();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allCamerasConnectionStringPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
GlobalVar.allCamerasConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson);
|
if (GlobalVar.allCamerasConnectionString == null)
|
{
|
MessageBox.Show("相机加载失败!", "异常");
|
return false;
|
}
|
foreach (var CameraConnectionString in GlobalVar.allCamerasConnectionString)
|
{
|
BaseCamera camera = null;
|
Enum.TryParse<CameraBrand>(CameraConnectionString.Value, out CameraBrand brand);
|
switch (brand)
|
{
|
case CameraBrand.HRCamera:
|
{
|
camera = new HRCamera();
|
break;
|
}
|
case CameraBrand.LBCamera:
|
{
|
camera = new LBCamera();
|
break;
|
}
|
case CameraBrand.LocalCamera:
|
{
|
camera = new LocalCamera();
|
break;
|
}
|
case CameraBrand.HikCamera:
|
{
|
camera = new HikCamera();
|
break;
|
}
|
case CameraBrand.HikCodeReader:
|
{
|
camera = new HikCodeReader();
|
break;
|
}
|
case CameraBrand.MindCamera:
|
{
|
camera = new MindCamera();
|
break;
|
}
|
case CameraBrand.MicroCamera:
|
{
|
camera = new MicroCamera();
|
break;
|
}
|
default:
|
{
|
MessageBox.Show($"[{CameraConnectionString.Key}]品牌不支持!", "异常");
|
continue;
|
}
|
}
|
camera.SN = CameraConnectionString.Key;
|
if (!camera.InitDevice(CameraConnectionString.Key, IntPtr.Zero))
|
{
|
LogInfo($"初始化相机[{CameraConnectionString.Key}]失败", LogInfoType.ERROR);
|
if (camera != null)
|
{
|
camera.isGrabbing = false;
|
}
|
}
|
if (camera is LBCamera phmCamera)
|
{
|
if (GlobalVar.allLBCameras.ContainsKey(camera.SN) && phmCamera._isConnected)
|
{
|
phmCamera.UpdateSensorConfig(GlobalVar.allLBCameras[camera.SN]);
|
}
|
}
|
GlobalVar.dicCameras.TryAdd(CameraConnectionString.Key, camera);
|
}
|
|
return true;
|
}
|
|
public bool SaveAllCameras()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
GlobalVar.allCamerasConnectionString = new ConcurrentDictionary<string, string>();
|
|
foreach (var item in GlobalVar.dicCameras)
|
{
|
string CameraSN = item.Value.SN;// "TCP"
|
string CameraBrand = item.Value.Brand.ToString();//"1111"
|
|
if (string.IsNullOrEmpty(CameraSN) || string.IsNullOrEmpty(CameraBrand))
|
{
|
break;
|
}
|
GlobalVar.allCamerasConnectionString.TryAdd(CameraSN, CameraBrand);
|
}
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.allCamerasConnectionString, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allCamerasConnectionStringPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch (Exception)
|
{ }
|
}
|
File.WriteAllText(GlobalVar.allCamerasConnectionStringPath, strJson, Encoding.UTF8);
|
return true;
|
}
|
catch { return false; }
|
}
|
|
|
public bool LoadAllCommunicators(string allCommunicatorsConnectionStringPath)
|
{
|
try
|
{
|
if (!File.Exists(allCommunicatorsConnectionStringPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allCommunicatorsConnectionStringPath);
|
SaveAllCommunicators();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allCommunicatorsConnectionStringPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
|
GlobalVar.allCommunicatorsConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson);
|
if (GlobalVar.allCommunicatorsConnectionString == null)
|
{
|
MessageBox.Show("通讯端口加载失败!", "异常");
|
return false;
|
}
|
|
//清空通讯口会把所有通讯口断开连接
|
GlobalVar.dicCommunicators.Clear();
|
ConcurrentDictionary<string, string> clientsCommunicatorsConnectionString = new ConcurrentDictionary<string, string>();
|
foreach (var CommunicatorConnectionString in GlobalVar.allCommunicatorsConnectionString)
|
{
|
string CommunicatorName = CommunicatorConnectionString.Key;
|
string CommunicatorAddress = CommunicatorConnectionString.Value;
|
if (!string.IsNullOrEmpty(CommunicatorAddress) && CommunicatorAddress.Contains("SiemensLBS7"))
|
{
|
// 定义正则表达式以提取协议、IP 地址和端口
|
// 更新正则以支持可选的数据类型字段
|
string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\](?:\[(?<DataType>[^]]+)\])?$";
|
Match match = Regex.Match(CommunicatorAddress, pattern);
|
|
if (match.Success)
|
{
|
string ClassName = match.Groups["ClassName"].Value; // "TCP"
|
string IP = match.Groups["IP"].Value; // "127.0.0.1"
|
string Slot = match.Groups["Slot"].Value; // "1111"
|
string CpuType = match.Groups["CpuType"].Value;
|
string PlcAddress = match.Groups["PlcAddress"].Value;
|
string DataType = match.Groups["DataType"].Success ? match.Groups["DataType"].Value : "String";
|
|
if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Slot) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress))
|
{
|
break;
|
}
|
//利用反射创建实例
|
Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
|
if (type == null)
|
{
|
Debug.WriteLine("Class not found.");
|
return false;
|
}
|
var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator;
|
|
if (Communicator == null)
|
{
|
Debug.WriteLine("BaseCommunicator not found.");
|
return false;
|
}
|
|
Communicator.CommunicatorConnections.Add("地址", IP);
|
Communicator.CommunicatorConnections.Add("端口", Slot);
|
Communicator.CommunicatorConnections.Add("型号", CpuType);
|
Communicator.CommunicatorConnections.Add("变量地址", PlcAddress);
|
Communicator.CommunicatorConnections.Add("数据类型", DataType);
|
Communicator.CommunicatorName = CommunicatorName;
|
if (!Communicator.Connect())
|
{
|
LogInfo($"初始化通讯口[{CommunicatorName}]失败,原因是{Communicator.Msg}", LogInfoType.ERROR);
|
}
|
else
|
{
|
LogInfo($"初始化通讯口[{CommunicatorName}]成功", LogInfoType.PASS);
|
}
|
GlobalVar.dicCommunicators.TryAdd(CommunicatorName, Communicator);
|
}
|
else
|
{
|
Debug.WriteLine("No match found.");
|
}
|
}
|
else
|
{
|
// 定义正则表达式以提取协议、IP 地址和端口
|
//1. \((.*?)\):\(和 \) 是用于匹配括号的转义字符。
|
// (.*?) 是一个非贪婪的匹配,用来匹配类名(MyProcesses.Communicators.TCPServer 或 MyProcesses.Communicators.UARTPort)。
|
//2. ([^:] +):匹配冒号之前的部分,即地址(127.0.0.1 或 COM5)。这里使用了[^:] 来匹配除了冒号之外的任意字符。
|
//3. (\d +) :匹配端口号,确保它匹配一个或多个数字。
|
|
string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<PORT>[^]]+)\]$";
|
Match match = Regex.Match(CommunicatorAddress, pattern);
|
|
if (match.Success)
|
{
|
string ClassName = match.Groups["ClassName"].Value; // "TCP"
|
string IP = match.Groups["IP"].Value; // "127.0.0.1"
|
string PORT = match.Groups["PORT"].Value; // "1111"
|
|
if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
|
break;
|
|
//利用反射创建实例
|
Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
|
if (type == null)
|
{
|
Debug.WriteLine("Class not found.");
|
return false;
|
}
|
var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator;
|
|
if (Communicator == null)
|
{
|
Debug.WriteLine("BaseCommunicator not found.");
|
return false;
|
}
|
|
//TCP客户端最后再连接
|
if (Communicator is TCPClient)
|
{
|
clientsCommunicatorsConnectionString.TryAdd(CommunicatorConnectionString.Key, CommunicatorConnectionString.Value);
|
continue;
|
}
|
|
Communicator.CommunicatorConnections.Add("地址", IP);
|
Communicator.CommunicatorConnections.Add("端口", PORT);
|
Communicator.CommunicatorName = CommunicatorName;
|
if (!Communicator.Connect())
|
{
|
LogInfo($"初始化通讯口[{CommunicatorName}]失败,原因是{Communicator.Msg}", LogInfoType.ERROR);
|
}
|
else
|
{
|
LogInfo($"初始化通讯口[{CommunicatorName}]成功", LogInfoType.PASS);
|
}
|
GlobalVar.dicCommunicators.TryAdd(CommunicatorName, Communicator);
|
}
|
else
|
{
|
Debug.WriteLine("No match found.");
|
}
|
}
|
}
|
|
//TCP客户端最后连接
|
foreach (var CommunicatorConnectionString in clientsCommunicatorsConnectionString)
|
{
|
string CommunicatorName = CommunicatorConnectionString.Key;
|
string CommunicatorAddress = CommunicatorConnectionString.Value;
|
|
// 定义正则表达式以提取协议、IP 地址和端口
|
//1. \((.*?)\):\(和 \) 是用于匹配括号的转义字符。
|
// (.*?) 是一个非贪婪的匹配,用来匹配类名(MyProcesses.Communicators.TCPServer 或 MyProcesses.Communicators.UARTPort)。
|
//2. ([^:] +):匹配冒号之前的部分,即地址(127.0.0.1 或 COM5)。这里使用了[^:] 来匹配除了冒号之外的任意字符。
|
//3. (\d +) :匹配端口号,确保它匹配一个或多个数字。
|
|
var regex = new Regex(@"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<PORT>[^]]+)\]$");
|
var match = regex.Match(CommunicatorAddress);
|
|
if (match.Success)
|
{
|
string ClassName = match.Groups[1].Value; // "TCP"
|
string IP = match.Groups[2].Value; // "127.0.0.1"
|
string PORT = match.Groups[3].Value; // "1111"
|
|
if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
|
{
|
break;
|
}
|
|
//利用反射创建实例
|
Type type = IProcess.GetExecutingAssembly().GetType(ClassName);
|
if (type == null)
|
{
|
Debug.WriteLine("Class not found.");
|
return false;
|
}
|
var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator;
|
|
if (Communicator == null)
|
{
|
Debug.WriteLine("BaseCommunicator not found.");
|
return false;
|
}
|
|
Communicator.CommunicatorConnections.Add("地址", IP);
|
Communicator.CommunicatorConnections.Add("端口", PORT);
|
Communicator.CommunicatorName = CommunicatorName;
|
if (!Communicator.Connect())
|
{
|
LogInfo($"初始化通讯口[{CommunicatorName}]失败,原因是{Communicator.Msg}", LogInfoType.ERROR);
|
}
|
else
|
{
|
LogInfo($"初始化通讯口[{CommunicatorName}]成功", LogInfoType.PASS);
|
}
|
GlobalVar.dicCommunicators.TryAdd(CommunicatorName, Communicator);
|
}
|
else
|
{
|
Debug.WriteLine("No match found.");
|
}
|
}
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool SaveAllCommunicators()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
GlobalVar.allCommunicatorsConnectionString = new ConcurrentDictionary<string, string>();
|
foreach (var item in GlobalVar.dicCommunicators)
|
{
|
string ClassName = item.Value.GetType().FullName;// "TCP"
|
string IP = item.Value.CommunicatorConnections["地址"].ToString();//"127.0.0.1"
|
string PORT = item.Value.CommunicatorConnections["端口"].ToString();//"1111"
|
if (!string.IsNullOrEmpty(ClassName) && ClassName.Contains("SiemensLBS7"))
|
{
|
string CpuType = item.Value.CommunicatorConnections["型号"].ToString();
|
string PlcAddress = item.Value.CommunicatorConnections["变量地址"].ToString();
|
string DataType = item.Value.CommunicatorConnections.Contains("数据类型") ?
|
item.Value.CommunicatorConnections["数据类型"].ToString() : "String";
|
|
if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress))
|
{
|
break;
|
}
|
string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}][{DataType}]";
|
GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString);
|
}
|
else
|
{
|
if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT))
|
{
|
break;
|
}
|
string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}]";
|
GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString);
|
}
|
GlobalVar.dicCommunicators[item.Key].ClassName = ClassName;
|
}
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.allCommunicatorsConnectionString, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allCommunicatorsConnectionStringPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch (Exception)
|
{ }
|
}
|
File.WriteAllText(GlobalVar.allCommunicatorsConnectionStringPath, strJson, Encoding.UTF8);
|
foreach (var item in GlobalVar.dicCommunicators)
|
{
|
string ClassName = item.Value.GetType().FullName;// "TCP"
|
}
|
ConfigManager<ObservableConcurrentDictionary<string, BaseCommunicator>>.SaveConfig<ObservableConcurrentDictionary<string, BaseCommunicator>>(GlobalVar.dicCommunicators, GlobalVar.strApplicationPath + "\\所有产品\\" + GlobalVar.strProductName + "\\dicCommunicators.json");
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool LoadAllLBCameras(string allLBCamerasPath)
|
{
|
try
|
{
|
if (!File.Exists(allLBCamerasPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allLBCamerasPath);
|
SaveAllLBCameras();
|
return true;
|
}
|
GlobalVar.allLBCameras = ConfigManager<ConcurrentDictionary<string, PHM6000SensorConfig>>.LoadConfig<ConcurrentDictionary<string, PHM6000SensorConfig>>(GlobalVar.allCamerasLBPath);
|
}
|
catch
|
{
|
return false;
|
}
|
return true;
|
}
|
|
public bool SaveAllLBCameras()
|
{
|
try
|
{
|
if (GlobalVar.allLBCameras.Count >= 0)
|
{
|
ConfigManager<ConcurrentDictionary<string, PHM6000SensorConfig>>.SaveConfig<ConcurrentDictionary<string, PHM6000SensorConfig>>(GlobalVar.allLBCameras, GlobalVar.allCamerasLBPath);
|
}
|
else
|
{
|
return false;
|
}
|
}
|
catch
|
{
|
return false;
|
}
|
return true;
|
}
|
|
public bool LoadAllProcess(string allProcessConnectionStringPath)
|
{
|
try
|
{
|
if (!File.Exists(allProcessConnectionStringPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allProcessConnectionStringPath);
|
SaveAllProcess();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allProcessConnectionStringPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
|
List<string> lstProcessName = JsonConvert.DeserializeObject<List<string>>(strJson);
|
|
if (lstProcessName == null)
|
{
|
return false;
|
}
|
// 使用方式
|
var sortedKeys = lstProcessName
|
.OrderBy(k => k, new NaturalStringComparer())
|
.ToList();
|
GlobalVar.dicProcesses.Clear();
|
foreach (var ProcessName in sortedKeys)
|
{
|
GlobalVar.dicProcesses.TryAdd(ProcessName
|
, new ProcessRunBll(ProcessName, GlobalVar.dicCameras, GlobalVar.dicCommunicators));
|
}
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool SaveAllProcess()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.dicProcesses.Keys.ToList(), settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allProcessConnectionStringPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch { }
|
}
|
File.WriteAllText(GlobalVar.allProcessConnectionStringPath, strJson, Encoding.UTF8);
|
|
foreach (var process in GlobalVar.dicProcesses.Values)
|
{
|
if (!process.Save(out string msg))
|
{
|
LogInfo($"流程[{process.Name}]保存失败,原因:{msg}", LogInfoType.NOSHOW);
|
}
|
}
|
|
try
|
{
|
string json = JsonConvert.SerializeObject(GlobalVar.ControlStates, settings);
|
File.WriteAllText(GlobalVar.allRunSettingStringPath, json);
|
LogInfo($"流程运行设置保存成功", LogInfoType.INFO);
|
}
|
catch { }
|
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool LoadAllProcessVars(string allProcessVarsPath)
|
{
|
try
|
{
|
if (!File.Exists(allProcessVarsPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allProcessVarsPath);
|
SaveAllProcessVars();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allProcessVarsPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
|
IProcess.dicGlobalVars.Clear();
|
IProcess.dicGlobalVars = JsonConvert.DeserializeObject<ConcurrentDictionary<string, object>>(strJson);
|
if (IProcess.dicGlobalVars == null)
|
{
|
IProcess.dicGlobalVars = new ConcurrentDictionary<string, object>();
|
return false;
|
}
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool SaveAllProcessVars()
|
{
|
try
|
{
|
string strJson = string.Empty;
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
|
strJson = JsonConvert.SerializeObject(IProcess.dicGlobalVars, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
string directoryPath = Path.GetDirectoryName(GlobalVar.allProcessVarsPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch { }
|
}
|
|
File.WriteAllText(GlobalVar.allProcessVarsPath, strJson, Encoding.UTF8);
|
LogInfo($"全局变量保存成功", LogInfoType.INFO);
|
|
strJson = JsonConvert.SerializeObject(GlobalVar.dicLayout, settings);
|
//判断文件夹是否存在,防呆输入为文件名称
|
directoryPath = Path.GetDirectoryName(GlobalVar.allLayoutPath);
|
if (!Directory.Exists(directoryPath))
|
{
|
try
|
{
|
Directory.CreateDirectory(directoryPath);
|
}
|
catch { }
|
}
|
|
File.WriteAllText(GlobalVar.allLayoutPath, strJson, Encoding.UTF8);
|
LogInfo($"全局布局保存成功", LogInfoType.INFO);
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool LoadAllLayout(string allLayoutPath)
|
{
|
try
|
{
|
if (!File.Exists(allLayoutPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
AsyncLogHelper.Info("文件不存在创建空文件");
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(allLayoutPath);
|
SaveAllLayout();
|
return true;
|
}
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(allLayoutPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
|
GlobalVar.dicLayout.Clear();
|
GlobalVar.dicLayout = JsonConvert.DeserializeObject<ConcurrentDictionary<int, Forms.Pages.SettingPage.Layout>>(strJson);
|
if (GlobalVar.dicLayout == null)
|
{
|
GlobalVar.dicLayout = new ConcurrentDictionary<int, Forms.Pages.SettingPage.Layout>();
|
return false;
|
}
|
return true;
|
}
|
catch { return false; }
|
}
|
|
private void btn_GlobalVar_Click(object sender, EventArgs e)
|
{
|
GlobalVarForm globalVarForm = new GlobalVarForm(GlobalVar.allProcessVarsPath);
|
globalVarForm.ShowDialog();
|
}
|
|
private void btn_Login_Click(object sender, EventArgs e)
|
{
|
//this.Hide();
|
//MainWindow.InstanceLoginandConfirmation().ShowDialog();
|
//if (!MainWindow.InstanceLoginandConfirmation().isQuit && MainWindow.InstanceLoginandConfirmation().correctUser)
|
//{
|
// MainWindow.InstanceLoginandConfirmation().closeLoginFrm();
|
// if (UserManager.Instance.CurrentUser.EmployeePermission == UserPermission.Operator)
|
// {
|
// //操作员权限界面
|
// }
|
// else if (UserManager.Instance.CurrentUser.EmployeePermission == UserPermission.Engineer)
|
// {
|
// //技术员权限界面
|
// }
|
// else if (UserManager.Instance.CurrentUser.EmployeePermission == UserPermission.Administrator)
|
// {
|
// //管理员权限界面
|
// }
|
// this.Show();
|
//}
|
}
|
|
void SelectMainPage()
|
{
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action(() =>
|
{
|
if (materialTabControl.SelectedIndex == 0)
|
{
|
return;
|
}
|
materialTabControl.SelectedIndex = 0;
|
ckbAllowRun.Enabled = false;
|
materialTabControl.Enabled = false;
|
materialTabSelector.Enabled = false;
|
cmbProduct.Enabled = false;
|
}));
|
}
|
else
|
{
|
if (materialTabControl.SelectedIndex == 0)
|
{
|
return;
|
}
|
materialTabControl.SelectedIndex = 0;
|
ckbAllowRun.Enabled = false;
|
materialTabControl.Enabled = false;
|
materialTabSelector.Enabled = false;
|
cmbProduct.Enabled = false;
|
}
|
}
|
|
void UnSelectMainPage()
|
{
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action(() =>
|
{
|
ckbAllowRun.Enabled = true;
|
materialTabControl.Enabled = true;
|
materialTabSelector.Enabled = true;
|
cmbProduct.Enabled = true;
|
}));
|
}
|
else
|
{
|
ckbAllowRun.Enabled = true;
|
materialTabControl.Enabled = true;
|
materialTabSelector.Enabled = true;
|
cmbProduct.Enabled = true;
|
}
|
}
|
|
private void CommunicationProtocol(string msg, out ProtocolType ProtocolType, out string[] protocol, char splitChar = ';')
|
{
|
protocol = msg.Split(splitChar);
|
|
if (msg.StartsWith("PCS"))
|
{
|
if (protocol.Length >= 1)
|
{
|
ProtocolType = ProtocolType.ProductChange;
|
}
|
else
|
{
|
ProtocolType = ProtocolType.Error;
|
}
|
}
|
else if (msg.StartsWith("GVS"))
|
{
|
ProtocolType = ProtocolType.GetVersion;
|
}
|
else if (msg.StartsWith("NCS"))
|
{
|
if (protocol.Length >= 5)
|
{
|
ProtocolType = ProtocolType.NpointCaltab;
|
}
|
else
|
{
|
ProtocolType = ProtocolType.Error;
|
}
|
}
|
else if (msg.StartsWith("CCS"))
|
{
|
if (protocol.Length >= 5)
|
{
|
ProtocolType = ProtocolType.CenterCaltab;
|
}
|
else
|
{
|
ProtocolType = ProtocolType.Error;
|
}
|
}
|
else
|
{
|
ProtocolType = ProtocolType.Normal;
|
}
|
|
}
|
|
private void TriggerRunMessageReceived(string name, string msg)
|
{
|
if (msg == null || msg.Trim('\0', '\r', '\n', ' ', '\uFEFF') == "" || string.IsNullOrEmpty(msg))
|
{
|
return;
|
}
|
if (GlobalVar.strUserName.ToUpper() != "ADMIN")
|
{
|
SelectMainPage();
|
}
|
LogInfo(string.Format("通讯[{0}]接收到的消息\"{1}\"", name, msg), LogInfoType.INFO);
|
|
CommunicationProtocol(msg, out ProtocolType type, out string[] protocol);
|
|
switch (type)
|
{
|
case ProtocolType.ProductChange:
|
{
|
string ProductName = protocol[1];
|
BaseCommunicator SendCom = GlobalVar.dicCommunicators[name];
|
|
if (!cmbProduct.Items.Contains(ProductName) || cmbProduct.FindString(ProductName) < 0)
|
{
|
LogInfo(string.Format($"通讯[{name}]触发切换产品{ProductName}不存在!"), LogInfoType.ERROR);
|
GlobalVar.dicCommunicators[name].SendMessage($"PCE;0;");
|
LogInfo(string.Format("发送给[{0}]了消息\"{1}\"", name, "PCE;0;"), LogInfoType.INFO);
|
return;
|
}
|
|
if (cmbProduct.FindString(ProductName) >= 0)
|
{
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action(() =>
|
{
|
if (cmbProduct.Text != ProductName)
|
cmbProduct.SelectedIndex = cmbProduct.FindString(ProductName);
|
}));
|
}
|
else if (cmbProduct.Text != ProductName)
|
{
|
cmbProduct.SelectedIndex = cmbProduct.FindString(ProductName);
|
}
|
LogInfo(string.Format($"通讯[{name}]触发切换产品{ProductName}成功!"), LogInfoType.INFO);
|
GlobalVar.dicCommunicators[name].SendMessage($"PCE;1;");
|
LogInfo(string.Format("发送给[{0}]了消息\"{1}\"", name, "PCE;1;"), LogInfoType.INFO);
|
}
|
|
return;
|
}
|
case ProtocolType.GetVersion:
|
{
|
LogInfo(string.Format($"通讯[{name}]触发获取版本!"), LogInfoType.INFO);
|
GlobalVar.dicCommunicators[name].SendMessage($"PCE;1;");
|
break;
|
}
|
case ProtocolType.NpointCaltab:
|
{
|
LogInfo(string.Format($"通讯[{name}]触发多点标定,暂不支持!"), LogInfoType.ERROR);
|
return;
|
}
|
case ProtocolType.CenterCaltab:
|
{
|
LogInfo(string.Format($"通讯[{name}]触发中心标定,暂不支持!"), LogInfoType.ERROR);
|
return;
|
}
|
case ProtocolType.Error:
|
{
|
LogInfo(string.Format($"通讯[{name}]指令非法,请查询通讯交互表!"), LogInfoType.ERROR);
|
return;
|
}
|
}
|
|
var matchedItems = GlobalVar.dicProcessSetting
|
.Where(item =>
|
{
|
var value = item.Value;
|
var triggerComm = value["触发通讯"];
|
var triggerChar = value["触发字符"];
|
|
return triggerComm != null && triggerComm.Equals(name) &&
|
(string.IsNullOrEmpty(triggerChar?.ToString()) ||
|
msg.StartsWith(triggerChar.ToString()));
|
})
|
.ToList(); // 避免重复字典访问和装箱操作
|
|
if (matchedItems.Count <= 0)
|
{
|
return;
|
}
|
|
if (!ckbAllowRun.Checked)
|
{
|
LogInfo(string.Format($"检查到可被触发的流程,当前不为运行模式!"), LogInfoType.ERROR);
|
return;
|
}
|
|
GlobalVar.dicProcesses.Values.AsParallel().ForAll(v => v.bCompleted = false);
|
LogInfo(string.Format($"检查到可被触发的流程,清空所有流程运行完成标记位!"), LogInfoType.INFO);
|
Task.Factory.StartNew(() =>
|
{
|
Parallel.ForEach(matchedItems, item =>
|
{
|
string ProcessName = item.Value["流程名"];
|
LogInfo($"流程[{ProcessName}]开始运行", LogInfoType.INFO);
|
|
if (!GlobalVar.dicProcesses.ContainsKey(ProcessName))
|
{
|
LogInfo(string.Format("流程[{0}]不存在,请检查流程设置", ProcessName), LogInfoType.ERROR);
|
return;
|
}
|
|
ProcessRunBll RunBll = GlobalVar.dicProcesses[ProcessName];
|
if (RunBll == null || RunBll.bRuning)
|
{
|
LogInfo(string.Format("流程[{0}]上次未运行完成,触发失败", ProcessName)
|
, LogInfoType.ERROR);
|
return;
|
}
|
|
try
|
{
|
bool result = false;
|
string msg = string.Empty;
|
int times = Convert.ToInt32(item.Value["重测次数"].ToString());
|
string ConnecResult = item.Value["关联结果"];
|
|
if (times < 0)
|
{
|
result = RunBll.Run();
|
msg = RunBll.Msg;
|
|
if (!(string.IsNullOrEmpty(ConnecResult) || ConnecResult.Trim() == "未关联"))
|
{
|
if (!result)
|
{
|
LogInfo(string.Format("流程[{0}]运行结果失败,原因是[{1}]", ProcessName, msg), LogInfoType.NOSHOW);
|
}
|
RunBll.GetBooleanOutput(ConnecResult, out result);
|
RunBll.Result = result;
|
}
|
|
if (!result)
|
{
|
LogInfo($"流程[{ProcessName}]被强制运行成功", LogInfoType.WARN);
|
RunBll.Result = true;
|
result = true;
|
}
|
}
|
else
|
{
|
while (times >= 0)
|
{
|
result = RunBll.Run();
|
msg = RunBll.Msg;
|
if (!(string.IsNullOrEmpty(ConnecResult) || ConnecResult.Trim() == "未关联"))
|
{
|
if (!result)
|
{
|
LogInfo(string.Format("流程[{0}]运行结果失败,原因是[{1}]", ProcessName, msg), LogInfoType.NOSHOW);
|
}
|
|
RunBll.GetBooleanOutput(ConnecResult, out result);
|
RunBll.Result = result;
|
}
|
|
if (result)
|
{
|
break;
|
}
|
else if (!result && times > 0)
|
{
|
LogInfo(string.Format("流程[{0}]运行失败重新测试,剩余次数[{1}]", ProcessName, times), LogInfoType.WARN);
|
}
|
|
times--;
|
}
|
}
|
|
string ConnectProcess = item.Value["关联流程"];
|
if (!(ConnectProcess == null || string.IsNullOrEmpty(ConnectProcess) || ConnectProcess.Trim() == ""))
|
{
|
//用逗号或者分号去间隔关联流程
|
string[] arrConnectProcess;
|
if (ConnectProcess.Split(';').Length >= ConnectProcess.Split(',').Length)
|
{
|
arrConnectProcess = ConnectProcess.Split(';');
|
}
|
else
|
{
|
arrConnectProcess = ConnectProcess.Split(',');
|
}
|
|
foreach (string strConnectProcess in arrConnectProcess)
|
{
|
if (GlobalVar.dicProcesses.ContainsKey(strConnectProcess))
|
{
|
ProcessRunBll ConnectRunBll = GlobalVar.dicProcesses[strConnectProcess];
|
|
int waitTime = 10;
|
DateTime startTime = DateTime.Now;
|
while ((DateTime.Now - startTime).TotalSeconds < waitTime
|
&& (ConnectRunBll.bRuning || !ConnectRunBll.bCompleted))
|
{
|
LogInfo(string.Format("关联流程[{0}]未运行完成,剩余等待[{1}]s", strConnectProcess, (waitTime - ((DateTime.Now - startTime).TotalSeconds)))
|
, LogInfoType.NOSHOW);
|
Thread.Sleep(1000);
|
continue;
|
}
|
|
if (ConnectRunBll.bRuning || !ConnectRunBll.bCompleted)
|
{
|
GlobalVar.dicProcesses[ProcessName].Msg = string.Format("流程[{0}]未运行完成", ProcessName);
|
LogInfo(string.Format("关联流程[{0}]未运行完成", strConnectProcess), LogInfoType.ERROR);
|
result = false;
|
break;
|
}
|
else if (!ConnectRunBll.bRuning && ConnectRunBll.bCompleted)
|
{
|
LogInfo(string.Format("关联流程[{0}]运行完成", strConnectProcess), LogInfoType.INFO);
|
}
|
|
result &= ConnectRunBll.Result;
|
if (!ConnectRunBll.Result)
|
{
|
LogInfo($"流程[{ProcessName}]的关联流程[{strConnectProcess}]运行失败", LogInfoType.ERROR);
|
msg = $"关联流程[{strConnectProcess}]运行失败";
|
}
|
}
|
}
|
}
|
|
LogInfo(result ? $"流程[{ProcessName}]运行成功" : $"流程[{ProcessName}]运行失败,原因是{msg}", result ? LogInfoType.PASS : LogInfoType.ERROR);
|
|
string SendComName = result ? item.Value["成功通讯"] : item.Value["失败通讯"];
|
string SendMsg = result ? item.Value["成功字符"] : item.Value["失败字符"];
|
if (GlobalVar.dicCommunicators.ContainsKey(SendComName) && (!string.IsNullOrEmpty(SendMsg) || SendMsg.Trim() != ""))
|
{
|
GlobalVar.dicCommunicators[SendComName].SendMessage(SendMsg);
|
LogInfo(string.Format("发送给[{0}]了消息\"{1}\"", SendComName, SendMsg), LogInfoType.INFO);
|
}
|
|
}
|
catch (Exception ex)
|
{
|
LogInfo(string.Format("流程[{0}]运行发生了意外,原因是:{1}", ProcessName, ex.Message + $"【{ex.StackTrace}】"), LogInfoType.ERROR);
|
|
RunBll.Result = false;
|
RunBll.Msg = $"[意外]{ex.Message}";
|
}
|
finally
|
{
|
#region 从RunSettingPage和Layout中获取是否保存图片
|
|
string strImageType = "jpeg";
|
bool bSaveRunImage = false;
|
bool bSaveResultImage = false;
|
long lImageQuality = 100L;
|
|
//ckbSaveRunImage
|
if (GlobalVar.ControlStates.TryGetValue("ckbSaveRunImage_CheckBox", out object oSaveRunImage))
|
{
|
if (oSaveRunImage != null && oSaveRunImage is bool)
|
{
|
bSaveRunImage = (bool)oSaveRunImage;
|
}
|
}
|
|
//ckbSaveResultImage
|
if (GlobalVar.ControlStates.TryGetValue("ckbSaveResultImage_CheckBox", out object oSaveResultImage))
|
{
|
if (oSaveResultImage != null && oSaveResultImage is bool)
|
{
|
bSaveResultImage = (bool)oSaveResultImage;
|
}
|
}
|
|
//txtImageQuality
|
if (GlobalVar.ControlStates.TryGetValue("txtImageQuality_TextBox", out object oImageQuality))
|
{
|
if (oImageQuality != null && oImageQuality is string)
|
{
|
lImageQuality = Convert.ToInt64((string)oImageQuality);
|
}
|
}
|
|
//cmbImageType
|
if (GlobalVar.ControlStates.TryGetValue("cmbImageType_ComboBox", out object oImageType))
|
{
|
try
|
{
|
// 动态解析ComboBox数据
|
var json = JsonConvert.SerializeObject(oImageType);
|
var comboData = JsonConvert.DeserializeAnonymousType(json, new
|
{
|
Items = new List<object>(),
|
SelectedIndex = 0
|
});
|
|
if (comboData != null && comboData.Items.Count > 0)
|
{
|
strImageType = comboData.Items[comboData.SelectedIndex].ToString();
|
}
|
}
|
catch { }
|
}
|
|
// 生成图片并显示到控件中
|
HObject InputImage = null;
|
HObject RecordImage = null;
|
|
foreach (var layout in GlobalVar.dicLayout.Values
|
.Where(layout => layout.ProcessName == ProcessName)
|
.ToList())
|
{
|
string title = layout.Title;
|
string strImagePath = layout.SaveImageDir;
|
if (!AllProcessesPage.dicProcessControls.ContainsKey(title))
|
{
|
continue;
|
}
|
|
RunBll.GetImage(layout, out InputImage, out RecordImage);
|
AllProcessesPage.dicProcessControls[title].ShowHoImage(RecordImage);
|
|
if (!string.IsNullOrEmpty(layout.SaveImageDir))
|
{
|
string fileNameHead = layout.SaveImageHead;
|
|
string result = Regex.Replace(fileNameHead, @"\{[^}]+\}", match =>
|
{
|
// 去除{}只保留括号内的内容
|
string content = match.Value;
|
content = content.Trim('{', '}'); // 去除首尾的{}
|
|
RunBll.GetStringOutput(content, out string str);
|
return str;
|
});
|
|
string fileName = $"{result}-[{DateTime.Now.ToString("HH.mm.ss.ffff")}]";
|
|
// 使用正则表达式替换所有非法字符
|
string invalidChars = Regex.Escape(new string(Path.GetInvalidFileNameChars()));
|
string pattern = $"[{invalidChars}]";
|
fileName = Regex.Replace(fileName, pattern, "-");
|
|
strImagePath = Regex.Replace(strImagePath, @"\{[^}]+\}", match =>
|
{
|
// 去除{}只保留括号内的内容
|
string content = match.Value;
|
content = content.Trim('{', '}'); // 去除首尾的{}
|
|
RunBll.GetStringOutput(content, out string str);
|
return str;
|
});
|
|
if (bSaveRunImage)
|
{
|
// 最后一级目录必须为年月日,会根据时间来删除旧图片
|
string directoryPath = Path.Combine(strImagePath, $"{ProcessName}\\原图\\{RunBll.Result}\\{DateTime.Now.ToString("yyyyMMdd")}\\");
|
LB_SmartVision.Tool.Tool.AddRealImage(InputImage, directoryPath, fileName, strImageType, lImageQuality);
|
}
|
|
if (bSaveResultImage)
|
{
|
// 最后一级目录必须为年月日,会根据时间来删除旧图片
|
string directoryPath = Path.Combine(strImagePath, $"{ProcessName}\\截图\\{RunBll.Result}\\{DateTime.Now.ToString("yyyyMMdd")}\\");
|
LB_SmartVision.Tool.Tool.AddRealImage(RecordImage, directoryPath, fileName, "jpg", 50L);
|
}
|
}
|
}
|
|
foreach (var csv in GlobalVar.dicCsvSetting.Values
|
.Where(csv => csv.ProcessName == ProcessName)
|
.ToList())
|
{
|
if (RunBll.GetCsv(csv
|
, out List<string> DataTitle, out Dictionary<string, object> ResultData))
|
{
|
string filePath = Path.Combine(GlobalVar.strPathCsv, $"{ProcessName}.csv");
|
LB_SmartVision.Tool.Tool.SaveData(filePath, DataTitle, ResultData);
|
}
|
}
|
#endregion
|
}
|
});
|
});
|
}
|
|
private void VisionForm_FormClosing(object sender, FormClosingEventArgs e)
|
{
|
SaveAllSetting();
|
if (MessageBox.Show("是否关闭软件?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)//
|
{
|
e.Cancel = true;
|
return;
|
}
|
//关闭窗体释放资源
|
AsyncLogHelper.Dispose();
|
foreach (BaseCamera camera in GlobalVar.dicCameras.Values)
|
{
|
camera.Dispose();
|
}
|
foreach (BaseCommunicator communicator in GlobalVar.dicCommunicators.Values)
|
{
|
communicator.Disconnect();
|
}
|
|
FormClosing -= VisionForm_FormClosing;
|
|
//try
|
//{
|
// Process[] processes = System.Diagnostics.Process.GetProcesses(); //获得所有进程
|
// foreach (Process p in processes)
|
// {
|
// if (p.ProcessName == "LB_SmartVision" && p.StartTime < DateTime.Now.AddMilliseconds(-300))
|
// {
|
// p.Kill();
|
// }
|
// }
|
//}
|
//catch { }
|
|
KillAllTargetProcesses();
|
}
|
|
/// <summary>
|
/// 杀进程逻辑
|
/// </summary>
|
private void KillAllTargetProcesses()
|
{
|
try
|
{
|
// 1. 获取当前进程ID,避免杀死自己
|
int currentProcessId = Process.GetCurrentProcess().Id;
|
// 2. 模糊匹配进程名(忽略大小写),覆盖vshost/后缀等情况
|
var targetProcesses = Process.GetProcesses()
|
.Where(p =>
|
p.ProcessName.IndexOf("LB_SmartVision", StringComparison.OrdinalIgnoreCase) >= 0
|
&& p.Id == currentProcessId);
|
|
foreach (var p in targetProcesses)
|
{
|
try
|
{
|
if (!p.HasExited)
|
{
|
// 先尝试优雅关闭WinForm程序(比直接Kill更友好)
|
p.CloseMainWindow();
|
// 等待500ms,看是否正常退出
|
if (!p.WaitForExit(500))
|
{
|
p.Kill(); // 强制杀死
|
p.WaitForExit(1000); // 等待进程完全终止
|
}
|
}
|
p.Dispose(); // 释放进程资源,避免句柄泄漏
|
}
|
catch (Exception ex)
|
{
|
// 记录异常但不中断,比如权限不足的情况
|
System.IO.File.AppendAllText("kill_process_log.txt", $"[{DateTime.Now}] 杀死进程失败: {ex.Message}\r\n");
|
}
|
}
|
|
// 额外延迟,确保文件句柄完全释放
|
Thread.Sleep(1000);
|
}
|
catch (Exception)
|
{
|
// 静默失败,不影响程序退出
|
}
|
}
|
|
private void btn_Run_Click(object sender, EventArgs e)
|
{
|
//var matchedItems = GlobalVar.dicProcessSetting
|
// .Where(item =>
|
// {
|
// var value = item.Value;
|
// var triggerComm = value["触发通讯"];
|
// var triggerChar = value["触发字符"];
|
// return triggerComm != null && !triggerComm.Equals("无");
|
// //return triggerComm != null && triggerComm.Equals(name) &&
|
// // (string.IsNullOrEmpty(triggerChar?.ToString()) ||
|
// // msg.StartsWith(triggerChar.ToString()));
|
// })
|
// .ToList(); // 避免重复字典访问和装箱操作
|
//if (matchedItems.Count <= 0)
|
//{
|
// return;
|
//}
|
//foreach (var item in matchedItems)
|
//{
|
// Task.Factory.StartNew(() =>
|
// {
|
// TriggerRunMessageReceived(item.Value["触发通讯"], item.Value["触发字符"]);
|
// });
|
//}
|
foreach (var item in GlobalVar.dicCameras.Keys)
|
{
|
GlobalVar.dicCameras[item].StartSingleGrab();
|
}
|
}
|
|
private void btn_RunContinuously_Click(object sender, EventArgs e)
|
{
|
if (this.ckbAllowRun.Checked)
|
{
|
if (btn_RunContinuously.Text.Equals("连续运行"))
|
{
|
_isTabSwitchAllowed = false;
|
btn_RunContinuously.Text = "暂停运行";
|
// 关闭使能
|
SelectMainPage();
|
btn_GlobalVar.Enabled = false;
|
btn_Login.Enabled = false;
|
btn_SingleRun.Enabled = false;
|
ckbAllowRun.Enabled = false;
|
foreach (var item in GlobalVar.dicCameras.Keys)
|
{
|
GlobalVar.dicCameras[item].StartContinuousGrab();
|
}
|
//Task.Factory.StartNew(() =>
|
//{
|
// var matchedItems = GlobalVar.dicProcessSetting
|
// .Where(item =>
|
// {
|
// var value = item.Value;
|
// var triggerComm = value["触发通讯"];
|
// var triggerChar = value["触发字符"];
|
// return triggerComm != null && !triggerComm.Equals("无");
|
// //return triggerComm != null && triggerComm.Equals(name) &&
|
// // (string.IsNullOrEmpty(triggerChar?.ToString()) ||
|
// // msg.StartsWith(triggerChar.ToString()));
|
// })
|
// .ToList(); // 避免重复字典访问和装箱操作
|
// while (btn_RunContinuously.Text.Equals("暂停运行"))
|
// {
|
// foreach (var item in matchedItems)
|
// {
|
// Task.Factory.StartNew(() =>
|
// {
|
// TriggerRunMessageReceived(item.Value["触发通讯"], item.Value["触发字符"]);
|
// });
|
// }
|
// //TriggerRunMessageReceived(matchedItems[0].Value["触发通讯"], matchedItems[0].Value["触发字符"]);
|
// Thread.Sleep(3500);
|
// }
|
// //this.Invoke(() =>
|
// //{
|
// //});
|
//});
|
}
|
else if (btn_RunContinuously.Text.Equals("暂停运行"))
|
{
|
btn_RunContinuously.Text = "连续运行";
|
foreach (var item in GlobalVar.dicCameras.Keys)
|
{
|
GlobalVar.dicCameras[item].StopGrabbing();
|
}
|
// 启动使能
|
UnSelectMainPage();
|
btn_GlobalVar.Enabled = true;
|
btn_Login.Enabled = true;
|
btn_SingleRun.Enabled = true;
|
ckbAllowRun.Enabled = true;
|
Thread.Sleep(100);
|
_isTabSwitchAllowed = true;
|
}
|
}
|
}
|
|
private void cmbProduct_SelectedValueChanged(object sender, EventArgs e)
|
{
|
if (cmbProduct.SelectedItem == null || cmbProduct.SelectedItem?.ToString() == GlobalVar.strProductName)
|
{
|
return;
|
}
|
|
if (cmbProduct.SelectedItem?.ToString() == "编辑")
|
{
|
using (CreateProductForm createDatabaseForm = new CreateProductForm())
|
{
|
createDatabaseForm.ShowDialog();
|
}
|
}
|
else
|
{
|
//变更前保存现有配置
|
SaveAllSetting();
|
|
LogInfo($"产品从{GlobalVar.strProductName}切换{cmbProduct.SelectedItem?.ToString()}", LogInfoType.WARN);
|
|
LB_SmartVision.Tool.Tool.WriteConfig("数据库名称", cmbProduct.SelectedItem?.ToString());
|
GlobalVar.strProductName = cmbProduct.SelectedItem?.ToString();
|
|
foreach (BaseCamera camera in GlobalVar.dicCameras.Values)
|
{
|
camera.TriggerRunMessageReceived -= TriggerRunMessageReceived;
|
camera.Dispose();
|
}
|
GlobalVar.dicCameras.Clear();
|
|
foreach (BaseCommunicator communicator in GlobalVar.dicCommunicators.Values)
|
{
|
communicator.TriggerRunMessageReceived -= TriggerRunMessageReceived;
|
communicator.Disconnect();
|
}
|
GlobalVar.dicCommunicators.Clear();
|
|
//保存完现有配置后断开所有事件
|
foreach (var Process in GlobalVar.dicProcesses.Values)
|
{
|
Process.LogInfo -= LogInfo;
|
}
|
GlobalVar.dicProcesses.Clear();
|
|
//重新加载配置
|
this.VisionForm_Load(sender, e);
|
NowBom = string.Empty;
|
LB_SmartVision.Tool.Tool.WriteConfig("当前BOM", NowBom);
|
}
|
}
|
|
private void rich_Info_MouseDoubleClick(object sender, MouseEventArgs e)
|
{
|
this.BeginInvoke(new Action(() =>
|
{
|
this.rich_Info.Clear();
|
}));
|
}
|
|
private void cmbProduct_MouseDoubleClick(object sender, MouseEventArgs e)
|
{
|
this.BeginInvoke(new Action(() =>
|
{
|
cmbProduct.Items.Clear();
|
LB_SmartVision.Tool.Tool.ReadStringConfig("产品列表", out string Products);
|
List<string> lstProduct = (Products.Split(',')).ToList();
|
foreach (string DatabaseName in lstProduct)
|
{
|
cmbProduct.Items.Add(DatabaseName);
|
}
|
cmbProduct.Items.Add("编辑");
|
cmbProduct.Text = GlobalVar.strProductName;
|
}));
|
}
|
|
private void materialTabControl_SelectedIndexChanged(object sender, EventArgs e)
|
{
|
if (materialTabControl.SelectedTab == null || !_isTabSwitchAllowed)
|
{
|
return;
|
}
|
|
if (materialTabControl.SelectedIndex == 0)
|
{
|
this.btn_SingleRun.Enabled = true;
|
this.btn_RunContinuously.Enabled = true;
|
}
|
else
|
{
|
this.btn_SingleRun.Enabled = false;
|
this.btn_RunContinuously.Enabled = false;
|
}
|
|
// 切换 Tab 时强制重绘所有子控件
|
foreach (Control control in materialTabControl.SelectedTab.Controls)
|
{
|
control.Invalidate();
|
}
|
materialCombobox1.SelectedItem = materialTabControl.SelectedTab.Text;
|
}
|
}
|
}
|