using LB_VisionProcesses.Communicators;
|
using LB_VisionProcesses.Communicators.Tcom;
|
using LB_VisionProcesses.Communicators.USerCommunicator.T306CommandTool;
|
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.Reflection;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
|
namespace LB_VisionProcesses.Communicators
|
{
|
public partial class CommunicatorForm : Form
|
{
|
UserControl userControl = new UserControl();
|
|
BaseCommunicator communicator = new UARTPort();
|
|
CommunicatorConfig _comConfig = null;
|
|
CommunicatorConfig comConfig
|
{
|
get { return _comConfig; }
|
set
|
{
|
_comConfig = value;
|
if (value is T306CommandTool)
|
{
|
cmbType.Enabled = false;
|
txtMsg.Enabled = false;
|
ckbRuleCheck.Enabled = false;
|
}
|
else
|
{
|
cmbType.Enabled = true;
|
txtMsg.Enabled = true;
|
ckbRuleCheck.Enabled = true;
|
}
|
}
|
}
|
|
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)
|
{
|
// 使用 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;
|
|
try
|
{
|
//利用反射创建实例,命名规范:Tool+Edit,命名空间也要相同
|
string ClassName = comConfig.GetType().FullName + "Edit";
|
// 获取编辑控件类型
|
Type ClassType = Type.GetType(ClassName)
|
?? Assembly.GetExecutingAssembly().GetTypes()
|
.FirstOrDefault(t => t.Name == ClassName);
|
|
if (ClassType != null)
|
{
|
// 使用Activator.CreateInstance带参数创建
|
userControl = (UserControl)Activator.CreateInstance(ClassType, comConfig);
|
|
if (userControl != null)
|
{
|
userControl.Dock = DockStyle.Fill;
|
pnlSetting.Controls.Add(userControl);
|
}
|
}
|
}
|
catch { }
|
}
|
}
|
|
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;
|
|
lblIP.Text = "串口号";
|
lblIP.Text = "波特率";
|
|
cmbIP.Text = communicator.CommunicatorConnections["地址"].ToString();
|
txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
|
}
|
else if (communicator is LocalMonitor)
|
{
|
btnSend.Enabled = communicator.bConnected;
|
btnRuleSend.Enabled = communicator.bConnected;
|
|
cmbIP.Visible = false;
|
txtIP.Visible = true;
|
|
lblIP.Text = "监控文件";
|
lblIP.Text = "写入文件";
|
|
txtIP.Text = communicator.CommunicatorConnections["地址"].ToString();
|
txtPort.Text = communicator.CommunicatorConnections["端口"].ToString();
|
}
|
else
|
{
|
btnSend.Enabled = communicator.bConnected;
|
btnRuleSend.Enabled = false;
|
|
cmbIP.Visible = false;
|
txtIP.Visible = true;
|
|
lblIP.Text = " IP";
|
lblIP.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
|
{
|
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)
|
{
|
//if (communicator is UARTPort || communicator is ModbusRTUMaster)
|
//{
|
// byte[] HexByte = BaseCommunicator.strToHexByte(strReceiveMsg);
|
|
// strReceiveMsg = string.Join(" ", HexByte);
|
//}
|
|
// 如果当前不是 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 btnSend_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
communicator.SendMessage(txtSendMsg.Text);
|
|
ShowSendMsg(txtSendMsg.Text);
|
}
|
|
private void btnRuleSend_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
string SendMsg = txtSendMsg.Text;
|
|
byte[] HexByte = SendMsg.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
.Select(hex => Convert.ToByte(hex, 16))
|
.ToArray();
|
|
ushort crcHexByte = BaseCommunicator.CRC16Calculate(HexByte, HexByte.Length);
|
|
string crcString = crcHexByte.ToString("X4");
|
crcString = crcString.Insert(2, " ");
|
|
HexByte = BaseCommunicator.strToHexByte(SendMsg + " " + crcString);
|
//SendMsg = SendMsg + crcString;
|
|
communicator.SendMessage(HexByte);
|
|
ShowSendMsg(SendMsg + " " + crcString);
|
}
|
|
private void btnRun_Click(object sender, EventArgs e)
|
{
|
if (communicator == null)
|
return;
|
|
// 尝试转换字符串为枚举
|
if (!Enum.TryParse(cmbType.Text, out CommunicatorType type))
|
return;
|
|
if (comConfig is T306CommandTool)
|
{
|
if (comConfig.Run())
|
btnRun.BackColor = Color.Green;
|
else
|
btnRun.BackColor = Color.Red;
|
|
ShowSendMsg(comConfig.Params.Inputs["通讯消息"].ToString());
|
this.Refresh();
|
}
|
else
|
{
|
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();
|
}
|
}
|
}
|