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 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 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((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((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(); } } }