using LB_VisionProcesses.Communicators.SiemensS7;
|
using LB_VisionProcesses.Communicators.TCom;
|
using RJCP.IO.Ports;
|
using System;
|
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Data;
|
using System.Diagnostics;
|
using System.Drawing;
|
using System.IO.Ports;
|
using System.Linq;
|
using System.Net.Sockets;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
|
namespace LB_VisionProcesses.Communicators
|
{
|
public partial class CommunicatorForm : Form
|
{
|
BaseCommunicator communicator = new UARTPort();
|
CommunicatorConfig comConfig { get; set; }
|
|
ConcurrentDictionary<string, BaseCommunicator> dicCommunicators { get; set; }
|
|
string fullPath = string.Empty;
|
|
public CommunicatorForm()
|
{
|
InitializeComponent();
|
//没有传入通讯句柄情况下可自由连接
|
btnConnect.Enabled = true;
|
btnDisconnect.Enabled = false;
|
btnSend.Enabled = false;
|
btnRuleSend.Enabled = false;
|
|
//测试功能禁用
|
grpTest.Enabled = false;
|
}
|
|
public CommunicatorForm(ConcurrentDictionary<string, BaseCommunicator> dicCommunicators, CommunicatorConfig comConfig, string fullPath)
|
{
|
InitializeComponent();
|
//传入通讯句柄后禁用连接/断开按键和输入控件
|
grpSetting.Enabled = false;
|
|
this.dicCommunicators = dicCommunicators;
|
this.comConfig = comConfig;
|
this.fullPath = fullPath;
|
this.Text = comConfig.strProcessName;
|
|
foreach (var name in dicCommunicators.Keys)
|
cmbCom.Items.Add(name);
|
}
|
|
private void CommunicatorForm_Load(object sender, EventArgs e)
|
{
|
// 初始化数据类型
|
cmbDataType.Items.Clear();
|
cmbDataType.Items.AddRange(new string[] { "String", "Bool", "Byte", "Int", "DInt", "Real", "Double", "Word", "DWord" });
|
|
// 绑定索引改变事件
|
cmbDataType.SelectedIndexChanged += (s, ev) =>
|
{
|
if (communicator != null)
|
{
|
communicator.CommunicatorConnections.Add("数据类型", cmbDataType.Text);
|
}
|
};
|
|
// 使用 Enum.GetValues 获取 enum 类型的所有值
|
foreach (CommunicatorType type in Enum.GetValues(typeof(CommunicatorType)))
|
{
|
cmbType.Items.Add(type.ToString());
|
}
|
|
// ... (保持不变)
|
|
//选择Com会触发ValueChanged事件,没有输入通讯口的情况下选择到-1
|
if (comConfig != null)
|
{
|
string CommunicatorName = comConfig.Params.Inputs["通讯口名"].ToString();
|
// 尝试转换字符串为枚举
|
if (!Enum.TryParse(comConfig.Params.Inputs["通讯类型"].ToString(), out CommunicatorType type))
|
type = CommunicatorType.Receiver;
|
|
bool bRuleCheck = Convert.ToBoolean(comConfig.Params.Inputs["是否启用CRC校验"].ToString());
|
string Msg = comConfig.Params.Inputs["通讯消息"].ToString();
|
|
int Index = cmbCom.FindString(CommunicatorName);
|
if (Index == -1 && cmbCom.Items.Count > 0)
|
{
|
//如果没有找到对应的通讯口名,则选择第一个可用的通讯口
|
CommunicatorName = cmbCom.Items[0].ToString();
|
Index = 0;
|
}
|
cmbCom.Text = CommunicatorName;
|
cmbCom.SelectedIndex = Index;
|
cmbType.Text = type.ToString();
|
ckbRuleCheck.Checked = bRuleCheck;
|
txtMsg.Text = Msg;
|
this.grpSetting.ForeColor= SystemColors.Control;
|
}
|
}
|
|
private void cmbCom_SelectedIndexChanged(object sender, EventArgs e)
|
{
|
//复原原通讯口设置
|
if (comConfig != null)
|
{
|
communicator.MessageReceived -= ShowReceiveMsg;
|
}
|
|
string name = cmbCom.Text;
|
if (dicCommunicators == null || !dicCommunicators.ContainsKey(name))
|
{
|
MessageBox.Show("该通讯口不存在!");
|
return;
|
}
|
|
//更换通讯口
|
|
communicator = dicCommunicators[name];
|
communicator.MessageReceived += ShowReceiveMsg;
|
|
if (communicator is UARTPort)
|
{
|
btnSend.Enabled = communicator.bConnected;
|
btnRuleSend.Enabled = communicator.bConnected;
|
|
cmbIP.Visible = true;
|
txtIP.Visible = false;
|
this.lblAddress.Visible = false;
|
this.txtAddress.Visible = false;
|
this.lblDataType.Visible = false;
|
this.cmbDataType.Visible = false;
|
|
|
lblIP.Text = "串口号";
|
lblIP.Text = "波特率"; // Bug: 这里 lblPort 应该被设置为 "波特率",但原代码复用了 lblIP? 不,lblIP.Text被设了两次。
|
lblPort.Text = "波特率"; // 修正原代码的潜在Bug
|
|
cmbIP.Text = communicator.CommunicatorConnections["地址"].ToString();
|
txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
|
this.grpSetting.ForeColor = SystemColors.Control;
|
}
|
else if (communicator is LocalMonitor)
|
{
|
btnSend.Enabled = communicator.bConnected;
|
btnRuleSend.Enabled = communicator.bConnected;
|
|
cmbIP.Visible = false;
|
txtIP.Visible = true;
|
this.lblAddress.Visible = false;
|
this.txtAddress.Visible = false;
|
this.lblDataType.Visible = false;
|
this.cmbDataType.Visible = false;
|
|
|
lblIP.Text = "监控文件";
|
lblPort.Text = "写入文件"; // 修正原代码可能的错误
|
|
txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
|
txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
|
this.grpSetting.ForeColor = SystemColors.Control;
|
}
|
else if (communicator is SiemensLBS7)
|
{
|
btnSend.Enabled = communicator.bConnected;
|
|
cmbIP.Visible = false;
|
txtIP.Visible = true;
|
this.lblAddress.Visible = true;
|
this.txtAddress.Visible = true;
|
this.lblDataType.Visible = true;
|
this.cmbDataType.Visible = true;
|
|
lblIP.Text = "IP";
|
lblPort.Text = "槽"; // 原代码这里是 lblIP.Text="槽" 覆盖了 "IP"
|
|
txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
|
txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
|
this.txtAddress.Text = communicator.CommunicatorConnections["变量地址"]?.ToString();
|
|
if (communicator.CommunicatorConnections.Contains("数据类型"))
|
this.cmbDataType.Text = communicator.CommunicatorConnections["数据类型"].ToString();
|
else
|
this.cmbDataType.Text = "String";
|
|
this.grpSetting.ForeColor = SystemColors.Control;
|
btnRuleSend.Visible = false;
|
}
|
else
|
{
|
btnSend.Enabled = communicator.bConnected;
|
btnRuleSend.Enabled = false;
|
this.lblAddress.Visible = false;
|
this.txtAddress.Visible = false;
|
this.lblDataType.Visible = false;
|
this.cmbDataType.Visible = false;
|
|
cmbIP.Visible = false;
|
txtIP.Visible = true;
|
|
lblIP.Text = " IP";
|
lblPort.Text = "端口";
|
|
txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
|
txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
|
}
|
}
|
|
private void cmbIP_Click(object sender, EventArgs e)
|
{
|
//统计可用端口
|
SerialPortStream temp = new SerialPortStream();
|
string[] ArryPort = temp.GetPortNames();
|
for (int i = 0; i < ArryPort.Length; i++)
|
cmbIP.Items.Add(ArryPort[i]);
|
}
|
|
private void btnConnect_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
if (communicator is UARTPort)
|
{
|
communicator.CommunicatorConnections.Add("地址", cmbIP.SelectedItem.ToString());
|
communicator.CommunicatorConnections.Add("端口", txtPort.Text);
|
}
|
else if (communicator is SiemensLBS7)
|
{
|
communicator.CommunicatorConnections.Add("地址", txtIP.Text);
|
communicator.CommunicatorConnections.Add("端口", txtPort.Text);
|
communicator.CommunicatorConnections.Add("变量地址", txtAddress.Text);
|
communicator.CommunicatorConnections.Add("数据类型", cmbDataType.Text);
|
}
|
else
|
{
|
communicator.CommunicatorConnections.Add("地址", txtIP.Text);
|
communicator.CommunicatorConnections.Add("端口", txtPort.Text);
|
}
|
|
bool connectSuccess = communicator.Connect();
|
if (connectSuccess)
|
{
|
communicator.MessageReceived -= ShowReceiveMsg;
|
communicator.MessageReceived += ShowReceiveMsg;
|
}
|
MessageBox.Show(connectSuccess ? "连接成功" : "连接失败,原因是" + communicator.Msg);
|
}
|
|
private void ShowReceiveMsg(string strReceiveMsg)
|
{
|
// 如果当前不是 UI 线程,则通过 Invoke 将操作调度到 UI 线程
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action<string>((msg) =>
|
{
|
// 更新 UI 控件,比如显示接收到的消息
|
this.txtReceiveMsg.Text += ("[接收]" + DateTime.Now.ToString() + ":" + msg + "\r\n");
|
}), strReceiveMsg);
|
}
|
else
|
{
|
// 如果已经在 UI 线程上,直接更新 UI
|
this.txtReceiveMsg.Text += ("[接收]" + DateTime.Now.ToString() + ":" + strReceiveMsg + "\r\n");
|
}
|
}
|
|
private void ShowSendMsg(string strSendMsg)
|
{
|
// 如果当前不是 UI 线程,则通过 Invoke 将操作调度到 UI 线程
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action<string>((msg) =>
|
{
|
// 更新 UI 控件,比如显示接收到的消息
|
this.txtReceiveMsg.Text += ("[发送]" + DateTime.Now.ToString() + ":" + msg + "\r\n");
|
}), strSendMsg);
|
}
|
else
|
{
|
// 如果已经在 UI 线程上,直接更新 UI
|
this.txtReceiveMsg.Text += ("[发送]" + DateTime.Now.ToString() + ":" + strSendMsg + "\r\n");
|
}
|
}
|
|
private void btnDisconnect_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
bool result = communicator.Disconnect();
|
|
if (result)
|
communicator.MessageReceived -= ShowReceiveMsg;
|
|
MessageBox.Show(result ? "断开成功" : "断开失败,原因是:" + communicator.Msg);
|
}
|
|
private void ShowLogMsg(string msg)
|
{
|
// 如果当前不是 UI 线程,则通过 Invoke 将操作调度到 UI 线程
|
if (this.InvokeRequired)
|
{
|
this.Invoke(new Action<string>((message) =>
|
{
|
this.txtReceiveMsg.AppendText("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + message + "\r\n");
|
this.txtReceiveMsg.ScrollToCaret();
|
}), msg);
|
}
|
else
|
{
|
this.txtReceiveMsg.AppendText("[" + DateTime.Now.ToString("HH:mm:ss.fff") + "] " + msg + "\r\n");
|
this.txtReceiveMsg.ScrollToCaret();
|
}
|
}
|
|
private void btnSend_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
if (communicator.SendMessage(txtSendMsg.Text))
|
{
|
ShowSendMsg(txtSendMsg.Text);
|
}
|
else
|
{
|
ShowLogMsg(communicator.Msg);
|
}
|
}
|
|
private void btnRuleSend_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
string SendMsg = txtSendMsg.Text;
|
|
byte[] HexByte = BaseCommunicator.strToHexByte(SendMsg);
|
ushort crcHexByte = BaseCommunicator.CRC16Calculate(HexByte, HexByte.Length);
|
|
string crcString = crcHexByte.ToString("X4");
|
//HexByte = strToHexByte(strSendMsg + crcString);
|
SendMsg = SendMsg + crcString;
|
|
if (communicator.SendMessage(SendMsg))
|
{
|
ShowSendMsg(SendMsg);
|
}
|
else
|
{
|
ShowLogMsg(communicator.Msg);
|
}
|
}
|
|
private void btnRun_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
// 尝试转换字符串为枚举
|
if (!Enum.TryParse(cmbType.Text, out CommunicatorType type))
|
return;
|
|
CommunicatorConfig OriComConfig = new CommunicatorConfig(dicCommunicators);
|
|
OriComConfig.Params.Inputs.Add("通讯口名", cmbCom.Text);
|
OriComConfig.Params.Inputs.Add("通讯类型", type);
|
OriComConfig.Params.Inputs.Add("是否启用CRC校验", ckbRuleCheck.Checked);
|
OriComConfig.Params.Inputs.Add("通讯消息", txtMsg.Text);
|
|
if (OriComConfig.Run())
|
{
|
btnRun.BackColor = Color.Green;
|
if (type == CommunicatorType.Receiver)
|
ShowReceiveMsg(OriComConfig.Params.Outputs["收到消息"].ToString());
|
else
|
ShowSendMsg(txtMsg.Text);
|
}
|
else
|
btnRun.BackColor = Color.Red;
|
|
}
|
|
private void cmbIP_MouseClick(object sender, MouseEventArgs e)
|
{
|
cmbIP.Items.Clear();
|
//统计可用端口
|
SerialPortStream temp = new SerialPortStream();
|
string[] ArryPort = temp.GetPortNames();
|
for (int i = 0; i < ArryPort.Length; i++)
|
cmbIP.Items.Add(ArryPort[i]);
|
}
|
|
private void CommunicatorForm_FormClosing(object sender, FormClosingEventArgs e)
|
{
|
//路径为空说明无需保存
|
if (string.IsNullOrEmpty(fullPath))
|
{
|
e.Cancel = false; //确认关闭窗体
|
return;
|
}
|
|
DialogResult res = MessageBox.Show("是否保存?", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); //保存结果信息
|
/// 参数1:显示文本,参数2:标题,参数3:按键类型,参数4:显示图标
|
if (res != DialogResult.Yes && res != DialogResult.No) //取消
|
{
|
e.Cancel = true; //取消关闭窗体
|
return;
|
}
|
|
if (res == DialogResult.Yes) //保存VPP
|
{
|
// 尝试转换字符串为枚举
|
if (!Enum.TryParse(cmbType.Text, out CommunicatorType type))
|
{
|
Debug.WriteLine("保存失败");
|
e.Cancel = false; //确认关闭窗体
|
return;
|
}
|
|
comConfig.Params.Inputs.Add("通讯口名", cmbCom.Text);
|
comConfig.Params.Inputs.Add("通讯类型", type);
|
comConfig.Params.Inputs.Add("是否启用CRC校验", ckbRuleCheck.Checked);
|
comConfig.Params.Inputs.Add("通讯消息", txtMsg.Text);
|
|
string directoryPath = Path.GetDirectoryName(fullPath);
|
comConfig.Save(directoryPath);
|
|
e.Cancel = false; //确认关闭窗体
|
return;
|
}
|
}
|
|
private void CommunicatorForm_FormClosed(object sender, FormClosedEventArgs e)
|
{
|
if (communicator != null)
|
communicator.MessageReceived -= ShowReceiveMsg;
|
|
//路径为空说明为测试模式,需要释放通讯口
|
if (string.IsNullOrEmpty(fullPath) && communicator != null)
|
communicator.Dispose();
|
}
|
}
|
}
|