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<string, Dictionary<string, float>> _plcDataDict;
|
|
// 用于绑定到DataGridView的可编辑列表
|
private BindingList<PlcDataItem> _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<string, PlcConfig> concurrentDictionary = new Dictionary<string, PlcConfig>();
|
|
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}");
|
}
|
}
|
|
/// <summary>
|
/// 相机回调运行
|
/// </summary>
|
/// <param name="CCDName"></param>
|
/// <param name="image"></param>
|
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<Dictionary<string, Dictionary<string, PlcConfig>>>.SaveConfig<Dictionary<string, Dictionary<string, PlcConfig>>>(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();
|
}
|
}
|
}
|