| | |
| | | using HalconDotNet; |
| | | using LB_SmartVision.Forms; |
| | | using LB_SmartVision.Forms.Pages; |
| | | using LB_SmartVision.Forms.Pages.CameraPage; |
| | | using LB_SmartVision.Forms.Pages.CommunicatorPage; |
| | | using LB_SmartVision.Forms.Pages.HistoricalData; |
| | | 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_SmartVisionCommon; |
| | | using LB_SmartVisionLoginUI; |
| | | using LB_VisionProcesses; |
| | | using LB_VisionProcesses.Cameras; |
| | | using LB_VisionProcesses.Cameras.HRCameras; |
| | | using LB_VisionProcesses.Cameras.LBCameras; |
| | | 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 Sunny.UI; |
| | |
| | | { |
| | | public partial class VisionForm : Form |
| | | { |
| | | AllProcessesPage AllProcessesPage = new AllProcessesPage(); |
| | | AllProcessesPage AllProcessesPages = new AllProcessesPage(); |
| | | CamerasEditPage CamerasEditPage = new CamerasEditPage(); |
| | | HistoricalDataEditPage HistoricalDataEditPage = new HistoricalDataEditPage(); |
| | | CommunicatorsEditPage CommunicatorsEditPage = new CommunicatorsEditPage(); |
| | | SettingEditPage SettingEditPage = new SettingEditPage(); |
| | | MESEditPage MESEditPage = new MESEditPage(); |
| | |
| | | Assembly_LB_VisionProcessesDll = Assembly.Load(Assembly_LB_VisionProcessesBytes); |
| | | |
| | | GlobalVar.dicCommunicators.DictionaryChanged += CommunicatorsChanged; |
| | | GlobalVar.dicCameras.DictionaryChanged += CamerasChanged; |
| | | GlobalVar.dicProcesses.DictionaryChanged += ProcessRunBllChanged; |
| | | |
| | | //最开始就清空所有Tab页 |
| | | materialTabControl.TabPages.Clear(); |
| | | materialTabControl.Controls.Add(AllProcessesPage); |
| | | AllProcessesPages.controlsPanel.Dock = DockStyle.Fill; |
| | | materialTabControl.Controls.Add(AllProcessesPages); |
| | | |
| | | HistoricalDataEditPage.LogInfo += LogInfo; |
| | | materialTabControl.Controls.Add(new MyPage(HistoricalDataEditPage)); |
| | | |
| | | CamerasEditPage.LogInfo += LogInfo; |
| | | materialTabControl.Controls.Add(new MyPage(CamerasEditPage)); |
| | |
| | | { |
| | | //materialTabControl.TabPages[i].Font= new Font("Microsoft YaHei UI", 18F, FontStyle.Regular, GraphicsUnit.Point, 0); |
| | | } |
| | | |
| | | materialTabSelector.BaseTabControl = materialTabControl; |
| | | //materialTabSelector.Font = new Font("Microsoft YaHei UI", 18F, FontStyle.Regular, GraphicsUnit.Point, 0); |
| | | } |
| | |
| | | |
| | | 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 arg1, LogInfoType type) |
| | | 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 > 1000) |
| | | { |
| | | 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() |
| | |
| | | } |
| | | 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 = { |
| | | @"生产日志\Run", |
| | | @"生产日志\Debug", |
| | | @"生产日志\Error", |
| | | @"生产日志\Fatal", |
| | | @"生产日志\Warn", |
| | | }; |
| | | foreach (string path in paths) |
| | | { |
| | | EnsureDirectory(path); |
| | | } |
| | | if (!LB_SmartVision.Tool.Tool.ReadStringConfig("数据库名称", out string DateBaseName)) |
| | | { |
| | | DateBaseName = "产品0"; |
| | |
| | | } |
| | | LB_SmartVision.Tool.Tool.ReadStringConfig("User ID", out string User_ID); |
| | | LB_SmartVision.Tool.Tool.ReadStringConfig("Password", out string Password); |
| | | |
| | | GlobalVar.strProductName = DateBaseName; |
| | | |
| | | //加载通讯 |
| | | 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); |
| | | |
| | | //必须先加载相机和通讯端口,因为流程加载过程中会用到相机和通讯口 |
| | | |
| | | } |
| | | //加载全局变量 |
| | | 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("运动控制参数加载失败", 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); |
| | | } |
| | | |
| | | //显示所有产品 |
| | | com_ProductName.Items.Clear(); |
| | | LB_SmartVision.Tool.Tool.ReadStringConfig("产品列表", out string Products); |
| | | List<string> lstProduct = (Products.Split(',')).ToList(); |
| | | foreach (string DatabaseName in lstProduct) |
| | | { |
| | | com_ProductName.Items.Add(DatabaseName); |
| | | } |
| | | com_ProductName.Items.Add("新增"); |
| | | |
| | | com_ProductName.Text = GlobalVar.strProductName; |
| | | this.WindowState = FormWindowState.Maximized; |
| | | DatabaseRecordProductDataHelper.InitializeDatabase(); |
| | | } |
| | | |
| | | public void SaveAllSetting() |
| | |
| | | SaveAllProcessSetting(); |
| | | SaveAllLayout(); |
| | | SaveAllCsv(); |
| | | SaveMotionControlDatas(); |
| | | } |
| | | public bool LoadMotionControlDatas(string alMotionControlDataPath) |
| | | { |
| | | try |
| | | { |
| | | GlobalVar.dicMotionControlData = ConfigManager<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>.LoadConfig<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>(alMotionControlDataPath); |
| | | } |
| | | catch |
| | | { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | public bool SaveMotionControlDatas() |
| | | { |
| | | try |
| | | { |
| | | ConcurrentDictionary<string, List<string>> removeCameraSN = new ConcurrentDictionary<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].Keys.Remove(itemSN); |
| | | } |
| | | } |
| | | ConfigManager<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>.SaveConfig<ConcurrentDictionary<string, ConcurrentDictionary<string, RecordMotionControlData>>>(GlobalVar.dicMotionControlData, GlobalVar.allMotionControlDataPath); |
| | | } |
| | | catch |
| | | { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | public bool LoadAllCameras(string allCamerasConnectionStringPath) |
| | |
| | | strJson = streamReader.ReadToEnd(); |
| | | streamReader.Close(); |
| | | } |
| | | |
| | | GlobalVar.allCamerasConnectionString = JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(strJson); |
| | | if (GlobalVar.allCamerasConnectionString == null) |
| | | { |
| | |
| | | switch (brand) |
| | | { |
| | | case CameraBrand.HRCamera: |
| | | //camera = new HRCamera(); |
| | | break; |
| | | { |
| | | camera = new HRCamera(); |
| | | break; |
| | | } |
| | | case CameraBrand.LBCamera: |
| | | //camera = new LBCamera(); |
| | | break; |
| | | { |
| | | camera = new LBCamera(); |
| | | break; |
| | | } |
| | | default: |
| | | MessageBox.Show($"[{CameraConnectionString.Key}]品牌不支持!", "异常"); |
| | | continue; |
| | | { |
| | | MessageBox.Show($"[{CameraConnectionString.Key}]品牌不支持!", "异常"); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | camera.SN = CameraConnectionString.Key; |
| | | if (!camera.InitDevice(CameraConnectionString.Key, this.Handle)) |
| | | if (!camera.InitDevice(CameraConnectionString.Key, IntPtr.Zero)) |
| | | { |
| | | LogInfo($"初始化相机[{CameraConnectionString.Key}]失败", LogInfoType.ERROR); |
| | | if (camera != null) |
| | |
| | | string CameraBrand = item.Value.Brand.ToString();//"1111" |
| | | |
| | | if (string.IsNullOrEmpty(CameraSN) || string.IsNullOrEmpty(CameraBrand)) |
| | | { |
| | | break; |
| | | |
| | | } |
| | | GlobalVar.allCamerasConnectionString.TryAdd(CameraSN, CameraBrand); |
| | | } |
| | | var settings = new JsonSerializerSettings |
| | |
| | | { |
| | | string CommunicatorName = CommunicatorConnectionString.Key; |
| | | string CommunicatorAddress = CommunicatorConnectionString.Value; |
| | | |
| | | // 定义正则表达式以提取协议、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) |
| | | if (!string.IsNullOrEmpty(CommunicatorAddress) && CommunicatorAddress.Contains("SiemensLBS7")) |
| | | { |
| | | string ClassName = match.Groups["ClassName"].Value; // "TCP" |
| | | string IP = match.Groups["IP"].Value; // "127.0.0.1" |
| | | string PORT = match.Groups["PORT"].Value; // "1111" |
| | | // 定义正则表达式以提取协议、IP 地址和端口 |
| | | // 更新正则以支持可选的数据类型字段 |
| | | string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\](?:\[(?<DataType>[^]]+)\])?$"; |
| | | Match match = Regex.Match(CommunicatorAddress, pattern); |
| | | |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT)) |
| | | break; |
| | | |
| | | //利用反射创建实例 |
| | | Type type = IProcess.GetExecutingAssembly().GetType(ClassName); |
| | | if (type == null) |
| | | if (match.Success) |
| | | { |
| | | Debug.WriteLine("Class not found."); |
| | | return false; |
| | | } |
| | | var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator; |
| | | 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 (Communicator == null) |
| | | { |
| | | Debug.WriteLine("BaseCommunicator not found."); |
| | | return false; |
| | | } |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Slot) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress)) |
| | | break; |
| | | |
| | | //TCP客户端最后再连接 |
| | | if (Communicator is TCPClient) |
| | | { |
| | | clientsCommunicatorsConnectionString.TryAdd(CommunicatorConnectionString.Key, CommunicatorConnectionString.Value); |
| | | continue; |
| | | } |
| | | //利用反射创建实例 |
| | | Type type = IProcess.GetExecutingAssembly().GetType(ClassName); |
| | | if (type == null) |
| | | { |
| | | Debug.WriteLine("Class not found."); |
| | | return false; |
| | | } |
| | | var Communicator = Activator.CreateInstance(type, CommunicatorName) as BaseCommunicator; |
| | | |
| | | Communicator.CommunicatorConnections.Add("地址", IP); |
| | | Communicator.CommunicatorConnections.Add("端口", PORT); |
| | | Communicator.CommunicatorName = CommunicatorName; |
| | | if (!Communicator.Connect()) |
| | | LogInfo($"初始化通讯口[{CommunicatorName}]失败,原因是{Communicator.Msg}", LogInfoType.ERROR); |
| | | 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 |
| | | LogInfo($"初始化通讯口[{CommunicatorName}]成功", LogInfoType.PASS); |
| | | GlobalVar.dicCommunicators.TryAdd(CommunicatorName, Communicator); |
| | | { |
| | | Debug.WriteLine("No match found."); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | Debug.WriteLine("No match found."); |
| | | } |
| | | // 定义正则表达式以提取协议、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客户端最后连接 |
| | |
| | | string PORT = match.Groups[3].Value; // "1111" |
| | | |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT)) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | //利用反射创建实例 |
| | | Type type = IProcess.GetExecutingAssembly().GetType(ClassName); |
| | |
| | | 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 |
| | |
| | | { |
| | | 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)) |
| | | break; |
| | | |
| | | string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}]"; |
| | | GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString); |
| | | 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, |
| | |
| | | { } |
| | | } |
| | | 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; } |
| | |
| | | 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; } |
| | |
| | | foreach (var process in GlobalVar.dicProcesses.Values) |
| | | { |
| | | if (!process.Save(out string msg)) |
| | | { |
| | | LogInfo($"流程[{process.Name}]保存失败,原因:{msg}", LogInfoType.NOSHOW); |
| | | } |
| | | } |
| | | |
| | | try |
| | |
| | | |
| | | File.WriteAllText(GlobalVar.allLayoutPath, strJson, Encoding.UTF8); |
| | | LogInfo($"全局布局保存成功", LogInfoType.INFO); |
| | | |
| | | return true; |
| | | } |
| | | catch { return false; } |
| | |
| | | if (!File.Exists(allLayoutPath)) |
| | | { |
| | | Debug.WriteLine("文件不存在创建空文件"); |
| | | AsyncLogHelper.Info("文件不存在创建空文件"); |
| | | // 获取不带文件名的目录路径 |
| | | string directoryPath = Path.GetDirectoryName(allLayoutPath); |
| | | SaveAllLayout(); |
| | |
| | | } |
| | | 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(); |
| | | //} |
| | | } |
| | | |
| | | private void com_ProductName_SelectedValueChanged(object sender, EventArgs e) |
| | | { |
| | | if (com_ProductName.SelectedItem == null || com_ProductName.SelectedItem?.ToString() == GlobalVar.strProductName) |
| | | { |
| | | return; |
| | | } |
| | | if (com_ProductName.SelectedItem?.ToString() == "新增") |
| | | { |
| | | using (CreateProductForm createDatabaseForm = new CreateProductForm()) |
| | | { |
| | | createDatabaseForm.ShowDialog(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //变更前保存现有配置 |
| | | SaveAllSetting(); |
| | | LogInfo($"产品从{GlobalVar.strProductName}切换{com_ProductName.SelectedItem?.ToString()}", LogInfoType.WARN); |
| | | //Tool.WriteConfig("数据库名称", com_ProductName.SelectedItem?.ToString()); |
| | | GlobalVar.strProductName = com_ProductName.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); |
| | | } |
| | | } |
| | | private void TriggerRunMessageReceived(string name, string msg) |
| | | { |
| | | if (msg == null || msg.Trim('\0', '\r', '\n', ' ', '\uFEFF') == "" || string.IsNullOrEmpty(msg)) |
| | | { |
| | | return; |
| | | } |
| | | LogInfo(string.Format("通讯[{0}]接收到的消息\"{1}\"", name, msg), LogInfoType.INFO); |
| | | 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 (!ckb_AllowRun.Checked) |
| | | { |
| | | LogInfo(string.Format($"检查到可被触发的流程,当前不为运行模式!"), LogInfoType.ERROR); |
| | | return; |
| | | } |
| | | GlobalVar.dicProcesses.Values.AsParallel().ForAll(v => v.bCompleted = false); |
| | | LogInfo(string.Format($"检查到可被触发的流程,清空所有流程运行完成标记位!"), LogInfoType.INFO); |
| | | 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 = GlobalVar.dicProcesses[ProcessName].Run(); |
| | | msg = GlobalVar.dicProcesses[ProcessName].Msg; |
| | | if (!(string.IsNullOrEmpty(ConnecResult) || ConnecResult.Trim() == "未关联")) |
| | | { |
| | | GlobalVar.dicProcesses[ProcessName].GetBooleanOutput(ConnecResult, out result); |
| | | GlobalVar.dicProcesses[ProcessName].Result = result; |
| | | } |
| | | if (!result) |
| | | { |
| | | LogInfo($"流程[{ProcessName}]被强制运行成功", LogInfoType.WARN); |
| | | GlobalVar.dicProcesses[ProcessName].Result = true; |
| | | result = true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | while (times >= 0) |
| | | { |
| | | result = RunBll.Run(); |
| | | msg = RunBll.Msg; |
| | | if (!(string.IsNullOrEmpty(ConnecResult) || ConnecResult.Trim() == "未关联")) |
| | | { |
| | | 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 (!AllProcessesPages.dicProcessControls.ContainsKey(title)) |
| | | { |
| | | continue; |
| | | } |
| | | RunBll.GetImage(layout, out InputImage, out RecordImage); |
| | | AllProcessesPages.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; |
| | | } |
| | | } |
| | | } |
| | | |