using LB_SmartVisionCommon; using LB_VisionControls; using LB_VisionProcesses.Cameras; using LB_VisionProcesses.Communicators; using LB_VisionProcesses.Communicators.SiemensS7; using OpenVinoSharp.Extensions.model; 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.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; using System.Windows.Media.Media3D; using static ZXing.QrCode.Internal.Mode; namespace LB_SmartVision.Forms.Pages.MotionControlPage { public partial class MotionControlFormRead : Form { // 原始字典:Key是读取PLC地址,Value是的Key是写入PLC地址以及对应的值Float值 private Dictionary> _plcDataDict; // 用于绑定到DataGridView的可编辑列表 private BindingList _plcDataList; // DataGridView绑定的数据源 private BindingSource _bindingSource; private PlcConfig config; private DataTable signalTable; private BindingSource bindingSource; private string Name; UserPictureBox onlinePictureBox { get; set; } string communicatorsName { get; set; } public MotionControlFormRead() { InitializeComponent(); } string cameraSN = string.Empty; public MotionControlFormRead(string strCameraSN) { InitializeComponent(); if (string.IsNullOrEmpty(strCameraSN)) { return; } this.cmbSN.Items.Clear(); this.cmbSN.Items.Add(strCameraSN); onlinePictureBox = new UserPictureBox(uiGroupBoxImage); this.uiGroupBoxImage.Controls.Clear(); this.uiGroupBoxImage.Controls.Add(onlinePictureBox); onlinePictureBox.Dock = DockStyle.Fill; LoadConfigAndSetupGrid(); } Dictionary concurrentDictionary = new Dictionary(); public void Unsubscribe() { try { if (GlobalVar.dicCameras[this.cmbSN.Text] == null) { return; }//取消回调函数 GlobalVar.dicCameras[this.cmbSN.Text].ImageGrabbed -= GetImageBllComplete; } catch (Exception ex) { // 记录错误信息 Debug.WriteLine($"错误: {ex.Message}"); } } public void Subscribe() { try { if (GlobalVar.dicCameras[this.cmbSN.Text] == null) { return; } //取消回调函数 GlobalVar.dicCameras[this.cmbSN.Text].ImageGrabbed -= GetImageBllComplete; //加载回调函数 GlobalVar.dicCameras[this.cmbSN.Text].ImageGrabbed += GetImageBllComplete; } catch (Exception ex) { // 记录错误信息 Debug.WriteLine($"错误: {ex.Message}"); } } /// /// 相机回调运行 /// /// /// private void GetImageBllComplete(object sender, CameraEventArgs e) { if (e.Bitmap == null) { return; } lock (e.Bitmap) { if (this.InvokeRequired) // 检查是否需要在UI线程上调用 { this.Invoke(new Action(() => { onlinePictureBox.Image = e.Bitmap; })); // 递归调用自身,但这次在UI线程上 } else { onlinePictureBox.Image = e.Bitmap; } } } private void uiButtonGrabOnce_Click(object sender, EventArgs e) { if (GlobalVar.dicCameras[this.cmbSN.Text] == null) { return; } Task.Factory.StartNew(() => { GlobalVar.dicCameras[this.cmbSN.Text].SetTriggerMode(TriggerMode.On, TriggerSource.Software); DateTime startTime = DateTime.Now; // 当前时间 GlobalVar.dicCameras[this.cmbSN.Text].GetImageWithSoftTrigger(out Bitmap bitmap); }); } private void uiButtonCloseSoftGrab_Click(object sender, EventArgs e) { if (GlobalVar.dicCameras[this.cmbSN.Text] == null) { return; } Task.Factory.StartNew(() => { GlobalVar.dicCameras[this.cmbSN.Text].StopGrabbing(); GlobalVar.dicCameras[this.cmbSN.Text].SetTriggerMode(TriggerMode.On, TriggerSource.Software); GlobalVar.dicCameras[this.cmbSN.Text].StartGrabbing(); }); } private void uiButtonHardGrabWithPLC_Click(object sender, EventArgs e) { if (GlobalVar.dicCameras[this.cmbSN.Text] == null) { return; } Task.Factory.StartNew(() => { GlobalVar.dicCameras[this.cmbSN.Text].SetTriggerMode(TriggerMode.On, TriggerSource.Line0); GlobalVar.dicCameras[this.cmbSN.Text].StopGrabbing(); GlobalVar.dicCameras[this.cmbSN.Text].StartWith_HardTriggerModel(); }); } private void cmbSN_SelectedIndexChanged(object sender, EventArgs e) { this.cameraSN = this.cmbSN.Text; this.textBoxName.Text = "Camera" + GlobalVar.dicCameras[this.cmbSN.Text].SN; //加载回调函数 Subscribe(); } private void btnAdd_Click(object sender, EventArgs e) { using (var configForm = new ConfigForm(config, GlobalVar.allPlcSettingPath + "\\" + this.Name + ".json")) { if (configForm.ShowDialog() == DialogResult.OK) { config = S7ConfigService.LoadConfig(GlobalVar.allPlcSettingPath); LoadConfigAndSetupGrid(); UpdateConnectionStatus(); } } } // 数据类型转换辅助方法 private object ConvertValue(string dataType, string valueStr) { switch (dataType) { case "Bool": { if (bool.TryParse(valueStr, out bool b)) return b; if (valueStr == "1") return true; if (valueStr == "0") return false; throw new Exception("无效的布尔值"); } case "Byte": { return byte.Parse(valueStr); } case "Int": { return short.Parse(valueStr); } case "DInt": { return int.Parse(valueStr); } case "Real": { return float.Parse(valueStr); } case "String": { return valueStr; } default: { throw new NotSupportedException($"不支持的类型: {dataType}"); } } } private void LoadConfigAndSetupGrid() { config = S7ConfigService.LoadConfig(GlobalVar.allPlcSettingPath + "\\" + this.Name + ".json"); if (GlobalVar.allPlcSettings.Keys.Contains(Name)) { GlobalVar.allPlcSettings[Name] = config; } else { GlobalVar.allPlcSettings.TryAdd(Name, config); } ConfigManager>>.SaveConfig>>(GlobalVar.dicMPlcData, GlobalVar.allMPlcDataPath); // 构建 DataTable 用于展示信号(支持编辑值列) signalTable = new DataTable(); signalTable.Columns.Add("SignalName", typeof(string)); signalTable.Columns.Add("Address", typeof(string)); signalTable.Columns.Add("Value", typeof(string)); foreach (var signal in config.Signals) { string address = $"{signal.Area}"; if (signal.Area == "DB") address += $"{signal.DbNumber}.DB"; address += $"{signal.ByteOffset}.{signal.BitOffset}"; signalTable.Rows.Add(signal.SignalName, address, ""); } bindingSource = new BindingSource(); bindingSource.DataSource = signalTable; dgvSignals.DataSource = bindingSource; dgvSignals.Columns["SignalName"].HeaderText = "信号名称"; dgvSignals.Columns["SignalName"].ReadOnly = true; dgvSignals.Columns["Address"].HeaderText = "PLC 地址"; dgvSignals.Columns["Address"].ReadOnly = true; dgvSignals.Columns["Value"].HeaderText = "当前值"; dgvSignals.Columns["Value"].ReadOnly = true; // 允许用户编辑 UpdateConnectionStatus(); dgvSignals.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; dgvSignals.ForeColor = Color.Black; } private void UpdateConnectionStatus() { if (((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]) != null && ((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]).bConnected) { lblStatus.Text = $"已连接: {config.PlcIpAddress}"; lblStatus.ForeColor = Color.Green; } else { lblStatus.Text = "未连接"; lblStatus.ForeColor = Color.Red; } } private void btnOneClickRead_Click(object sender, EventArgs e) { if (((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]) == null || !((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]).bConnected) { System.Windows.Forms.MessageBox.Show("请先连接 PLC", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { for (int i = 0; i < config.Signals.Count; i++) { var signal = config.Signals[i]; object value = ((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]).ReadSignal(signal); config.Signals[i].Value = value?.ToString() ?? ""; signalTable.Rows[i]["Value"] = config.Signals[i].Value; //ShowLogMsg(signalTable.Rows[i]["Value"] + ":" + value?.ToString() ?? ""); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show($"批量读取失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void btnOneClickSetting_Click(object sender, EventArgs e) { if (((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]) == null || !((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]).bConnected) { System.Windows.Forms.MessageBox.Show("请先连接 PLC", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { int successCount = 0; for (int i = 0; i < config.Signals.Count; i++) { var signal = config.Signals[i]; string newValueStr = signalTable.Rows[i]["Value"]?.ToString(); if (!string.IsNullOrEmpty(newValueStr)) { object convertedValue = ConvertValue(signal.DataType, newValueStr); ((SiemensLBS7)GlobalVar.dicCommunicators[GlobalVar.currentCommunicators]).WriteSignal(signal, convertedValue); successCount++; } //ShowSendMsg(signalTable.Rows[i]["Value"] + ":" + newValueStr?.ToString() ?? ""); } System.Windows.Forms.MessageBox.Show($"批量写入完成,成功写入 {successCount} 个信号。", "写入结果", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show($"批量写入失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void btnSave_Click(object sender, EventArgs e) { LoadConfigAndSetupGrid(); } } }