using MainForm.ClassFile;
using ModBusClientSimple.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MainForm.FaForm
{
public partial class Form_PLCDB_ShowInfo : Form
{
#region ModbusTCP
ModbusClientHelper plc1 = new ModbusClientHelper(GlobalContext.Machine1Address, GlobalContext.MachinePort, 499);
#endregion ModbusTCP
#region 变量
///
/// 展示的工位名称
///
private string _StationName;
///
/// 记录信息方法的载体窗体
///
private Form_PLCDB _Form_PLCDB;
///
/// “工位可调试点位预览表.xlsx”文件的地址
///
private string filePath = AppDomain.CurrentDomain.BaseDirectory + "\\DBFile\\工位可调试点位预览表.xlsx";
private DataTable dt;
#endregion 变量
#region 单例
private static Form_PLCDB_ShowInfo _Form_PLCDB_ShowInfo;
public static Form_PLCDB_ShowInfo Singleton(string stationName, Form_PLCDB form_PLCDB)
{
if (_Form_PLCDB_ShowInfo == null)
{
_Form_PLCDB_ShowInfo = new Form_PLCDB_ShowInfo();
}
_Form_PLCDB_ShowInfo._StationName = stationName;
_Form_PLCDB_ShowInfo._Form_PLCDB = form_PLCDB;
_Form_PLCDB_ShowInfo.OnLoadData(); // 加载点位数据
return _Form_PLCDB_ShowInfo;
}
#endregion 单例
#region 窗体事件
public Form_PLCDB_ShowInfo()
{
InitializeComponent();
}
private void Form_PLCDB_ShowInfo_Load(object sender, EventArgs e)
{
try
{
this.Text = string.Concat(_StationName, " 工位DB详情");
// dgv_S0
dgv_DBInfo.ColumnHeadersDefaultCellStyle.BackColor = Color.WhiteSmoke;
dgv_DBInfo.ColumnHeadersDefaultCellStyle.ForeColor = Color.Black;
dgv_DBInfo.RectColor = Color.Gainsboro;
dgv_DBInfo.GridColor = Color.Gainsboro;
dgv_DBInfo.BackgroundColor = Color.White;
}
catch (Exception ex)
{
string str = ex.StackTrace;
MessageBox.Show("PLC交互工位DB详情页面初始化出错!异常信息:" + ex.Message);
_Form_PLCDB.AddMessage(LogType.Error, "PLC交互工位DB详情页面初始化出错!异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1) + ";异常信息:" + ex.Message.ToString());
}
}
private void Form_PLCDB_ShowInfo_VisibleChanged(object sender, EventArgs e)
{
if (!this.IsDisposed && this.Visible)
{
SBtn_GetDBValue_LoopStart.Enabled = true;
SBtn_GetDBValue_LoopStop.Enabled = false;
}
else if (!this.IsDisposed && !this.Visible)
{
if (cts != null)
{
cts.Cancel();
}
SBtn_GetDBValue_LoopStart.Enabled = true;
SBtn_GetDBValue_LoopStop.Enabled = false;
}
}
#endregion 窗体事件
#region 方法
///
/// dgv加载数据
///
private void OnLoadData()
{
try
{
if (!File.Exists(filePath))
{
MessageBox.Show($"‘{filePath}’文件不存在!未读到调试点位数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
dt = NPOIHelper.ReadExcel(filePath);
if (dt != null && dt.Rows.Count > 0)
{
dt.Rows.RemoveAt(0);
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][1] == DBNull.Value || !dt.Rows[i][1].ToString().Trim().Equals(_StationName))
{
dt.Rows.RemoveAt(i);
i--;
}
}
dgv_DBInfo.DataSource = dt.DefaultView;
}
else
{
dgv_DBInfo.DataSource = new DataTable().DefaultView;
MessageBox.Show($"‘{filePath}’文件未包含任何需要读取的数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
}
catch (Exception ex)
{
string str = ex.StackTrace;
MessageBox.Show("PLC交互工位DB详情页面表格加载数据出错!异常信息:" + ex.Message);
_Form_PLCDB.AddMessage(LogType.Error, "PLC交互工位DB详情页面表格加载数据出错!异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1) + ";异常信息:" + ex.Message.ToString());
}
}
#endregion 方法
// 刷新当前值
private void SBtn_GetDBValue_One_Click(object sender, EventArgs e)
{
try
{
if (dt == null)
{
return;
}
if (!plc1.IsConnected)
{
plc1.Connect();
}
int rowNum = 0;
foreach (DataRow row in dt.Rows)
{
if (row[5] != DBNull.Value && row[4] != DBNull.Value && !string.IsNullOrEmpty(row[5].ToString()) && !string.IsNullOrEmpty(row[4].ToString()))
{
string value = string.Empty;
string plcType = row[4].ToString();
int plcAddress = Convert.ToInt32(row[5].ToString());
switch (plcType)
{
case "Bool":
value = (plc1.ReadHoldingRegisters(plcAddress, 1).FirstOrDefault() == 1).ToString(); // 读取
break;
case "Int16":
value = plc1.ReadHoldingRegisters(plcAddress).ToString(); // 读取
break;
case "Int32":
value = plc1.ReadHoldingRegisters(plcAddress).ToString(); // 读取
break;
case "String<32>":
value = plc1.ReadHoldingRegisters(plcAddress, 32, 32).ToString(); // 读取
break;
case "Float":
value = plc1.ReadHoldingRegisters(plcAddress).ToString(); // 读取
break;
case "Bype<3>": // 日期yyyyMMdd;yyyy、MM、dd共占用3个地址位
string plcDate_Y = plc1.ReadHoldingRegisters(plcAddress, 1).FirstOrDefault().ToString("0000"); // 产品序列号的 当前日期_年
string plcDate_M = plc1.ReadHoldingRegisters(plcAddress + 1, 1).FirstOrDefault().ToString("00"); // 产品序列号的 当前日期_月
string plcDate_D = plc1.ReadHoldingRegisters(plcAddress + 2, 1).FirstOrDefault().ToString("00"); // 产品序列号的 当前日期_日
value = string.Concat(plcDate_Y, plcDate_M, plcDate_D); // 产品序列号的 当前日期
break;
default:
break;
}
dgv_DBInfo.Rows[rowNum].Cells[9].Value = value;
}
rowNum++;
}
}
catch (Exception ex)
{
string str = ex.StackTrace;
MessageBox.Show("PLC交互工位DB详情页面刷新当前值出错!异常信息:" + ex.Message);
_Form_PLCDB.AddMessage(LogType.Error, "PLC交互工位DB详情页面刷新当前值出错!异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1) + ";异常信息:" + ex.Message.ToString());
}
}
#region 循环刷新
///
/// 循环线程结束标志
///
private CancellationTokenSource cts;
///
/// 循环刷新当前值
///
private async void SBtn_GetDBValue_LoopStart_Click(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
SBtn_GetDBValue_LoopStart.Enabled = false;
SBtn_GetDBValue_LoopStop.Enabled = true;
await Task.Run(() => ThreadCode(cts.Token));
}
///
/// 停止循环刷新当前值
///
private void SBtn_GetDBValue_LoopStop_Click(object sender, EventArgs e)
{
cts.Cancel();
SBtn_GetDBValue_LoopStop.Enabled = false;
SBtn_GetDBValue_LoopStart.Enabled = true;
}
///
///
///
///
private void ThreadCode(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
try
{
if (dt == null)
{
return;
}
if (!plc1.IsConnected)
{
plc1.Connect();
}
int rowNum = 0;
foreach (DataRow row in dt.Rows)
{
if (row[5] != DBNull.Value && row[4] != DBNull.Value && !string.IsNullOrEmpty(row[5].ToString()) && !string.IsNullOrEmpty(row[4].ToString()))
{
string value = string.Empty;
string plcType = row[4].ToString();
int plcAddress = Convert.ToInt32(row[5].ToString());
switch (plcType)
{
case "Bool":
value = (plc1.ReadHoldingRegisters(plcAddress, 1).FirstOrDefault() == 1).ToString(); // 读取
break;
case "Int16":
value = plc1.ReadHoldingRegisters(plcAddress).ToString(); // 读取
break;
case "Int32":
value = plc1.ReadHoldingRegisters(plcAddress).ToString(); // 读取
break;
case "String<32>":
value = plc1.ReadHoldingRegisters(plcAddress, 32, 32).ToString(); // 读取
break;
case "Float":
value = plc1.ReadHoldingRegisters(plcAddress).ToString(); // 读取
break;
case "Bype<3>": // 日期yyyyMMdd;yyyy、MM、dd共占用3个地址位
string plcDate_Y = plc1.ReadHoldingRegisters(plcAddress, 1).FirstOrDefault().ToString("0000"); // 产品序列号的 当前日期_年
string plcDate_M = plc1.ReadHoldingRegisters(plcAddress + 1, 1).FirstOrDefault().ToString("00"); // 产品序列号的 当前日期_月
string plcDate_D = plc1.ReadHoldingRegisters(plcAddress + 2, 1).FirstOrDefault().ToString("00"); // 产品序列号的 当前日期_日
value = string.Concat(plcDate_Y, plcDate_M, plcDate_D); // 产品序列号的 当前日期
break;
default:
break;
}
dgv_DBInfo.Invoke(new Action(() =>
{
dgv_DBInfo.Rows[rowNum].Cells[9].Value = value;
}));
}
rowNum++;
}
}
catch (Exception ex)
{
string str = ex.StackTrace;
MessageBox.Show("PLC交互工位DB详情页面循环刷新当前值出错!异常信息:" + ex.Message);
cts.Cancel();
this.Invoke(new Action(() =>
{
SBtn_GetDBValue_LoopStart.Enabled = true;
SBtn_GetDBValue_LoopStop.Enabled = false;
}));
_Form_PLCDB.AddMessage(LogType.Error, "PLC交互工位DB详情页面循环刷新当前值出错!异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1) + ";异常信息:" + ex.Message.ToString());
}
Thread.Sleep(1000); // 等待
}
}
#endregion 循环刷新
///
/// 写入
///
private void 写入ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
int selectedRowIndex = dgv_DBInfo.SelectedIndex;
if (selectedRowIndex < 0 || selectedRowIndex > dgv_DBInfo.RowCount - 1)
{
MessageBox.Show("请先选择要写入的‘当前值’单元格", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
if (!plc1.IsConnected)
{
plc1.Connect();
}
if (dgv_DBInfo.Rows[selectedRowIndex].Cells[5].Value != DBNull.Value && dgv_DBInfo.Rows[selectedRowIndex].Cells[4].Value != DBNull.Value && !string.IsNullOrEmpty(dgv_DBInfo.Rows[selectedRowIndex].Cells[5].ToString()) && !string.IsNullOrEmpty(dgv_DBInfo.Rows[selectedRowIndex].Cells[4].ToString()))
{
string plcVName = dgv_DBInfo.Rows[selectedRowIndex].Cells[3].Value?.ToString(); // DB点位的变量名称
string plcType = dgv_DBInfo.Rows[selectedRowIndex].Cells[4].Value.ToString(); // DB点位的类型
int plcAddress = Convert.ToInt32(dgv_DBInfo.Rows[selectedRowIndex].Cells[5].Value.ToString()); // DB点位的地址
string plcVValue = dgv_DBInfo.Rows[selectedRowIndex].Cells[9].Value.ToString(); // DB点位的值
switch (plcType)
{
case "Bool":
if (plcVValue.ToLower() == "true")
{
plcVValue = "1";
}
else if (plcVValue.ToLower() == "false")
{
plcVValue = "0";
}
else
{
MessageBox.Show("写入失败!写入的值不是Bool类型!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
plc1.WriteSingleRegister(plcAddress, Convert.ToInt32(plcVValue)); // 写入
MessageBox.Show("写入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
case "Int16":
int value = 0;
try
{
value = Convert.ToInt32(plcVValue);
}
catch
{
MessageBox.Show("写入失败!写入的值不是Int16类型!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
plc1.WriteSingleRegister(plcAddress, value); // 写入
MessageBox.Show("写入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
case "Int32":
int value1 = 0;
try
{
value1 = Convert.ToInt32(plcVValue);
}
catch
{
MessageBox.Show("写入失败!写入的值不是Int32类型!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
plc1.WriteMultipleRegisters(plcAddress, value1); // 写入
MessageBox.Show("写入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
case "Float":
float value2 = 0;
try
{
value2 = Convert.ToSingle(plcVValue);
}
catch
{
MessageBox.Show("写入失败!写入的值不是Float类型!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
plc1.WriteMultipleRegisters(plcAddress, value2); // 写入
MessageBox.Show("写入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
case "String<32>":
if (plcVValue == null || plcVValue.Length < 1)
{
MessageBox.Show("写入失败!写入值的长度必须 > 1!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
}
plc1.WriteMultipleRegisters(plcAddress, plcVValue, 32); // 写入
MessageBox.Show("写入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
//case "Bype<3>": // 日期yyyyMMdd;yyyy、MM、dd共占用3个地址位
default:
MessageBox.Show("不支持修改该类型的数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
return;
break;
}
_Form_PLCDB.AddMessage(LogType.Info, $"用户【{_Form_PLCDB.currentRole}】将‘{plcVName}’【{plcAddress}】的DB值修改为‘{plcVValue}’!");
}
}
catch (Exception ex)
{
string str = ex.StackTrace;
MessageBox.Show("写入值失败!错误信息:" + ex.Message);
_Form_PLCDB.AddMessage(LogType.Error, "PLC交互工位DB详情页面写入当前值出错!异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1) + ";异常信息:" + ex.Message.ToString());
}
}
}
}