| | |
| | | lblType = new Label(); |
| | | lblAddress = new Label(); |
| | | lblIP = new Label(); |
| | | cmbDataType = new ComboBox(); |
| | | lblDataType = new Label(); |
| | | tableLayoutPanel2 = new TableLayoutPanel(); |
| | | btnRuleSend = new Button(); |
| | | btnSend = new Button(); |
| | |
| | | label3.AutoSize = true; |
| | | label3.Dock = DockStyle.Fill; |
| | | label3.ForeColor = Color.CornflowerBlue; |
| | | label3.Location = new Point(3, 100); |
| | | label3.Location = new Point(4, 125); |
| | | label3.Margin = new Padding(4, 0, 4, 0); |
| | | label3.Name = "label3"; |
| | | label3.Size = new Size(655, 20); |
| | | label3.Size = new Size(819, 25); |
| | | label3.TabIndex = 18; |
| | | label3.Text = "发送信息"; |
| | | label3.TextAlign = ContentAlignment.BottomLeft; |
| | |
| | | tableLayoutPanel1.Controls.Add(label3, 0, 1); |
| | | tableLayoutPanel1.Dock = DockStyle.Fill; |
| | | tableLayoutPanel1.Location = new Point(0, 0); |
| | | tableLayoutPanel1.Margin = new Padding(4, 4, 4, 4); |
| | | tableLayoutPanel1.Name = "tableLayoutPanel1"; |
| | | tableLayoutPanel1.RowCount = 5; |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 100F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 30F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 125F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 25F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 38F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F)); |
| | | tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); |
| | | tableLayoutPanel1.Size = new Size(661, 322); |
| | | tableLayoutPanel1.Size = new Size(827, 402); |
| | | tableLayoutPanel1.TabIndex = 26; |
| | | // |
| | | // grpReceive |
| | |
| | | grpReceive.Controls.Add(txtReceiveMsg); |
| | | grpReceive.Dock = DockStyle.Fill; |
| | | grpReceive.ForeColor = Color.CornflowerBlue; |
| | | grpReceive.Location = new Point(3, 193); |
| | | grpReceive.Location = new Point(4, 242); |
| | | grpReceive.Margin = new Padding(4, 4, 4, 4); |
| | | grpReceive.Name = "grpReceive"; |
| | | grpReceive.Size = new Size(655, 126); |
| | | grpReceive.Padding = new Padding(4, 4, 4, 4); |
| | | grpReceive.Size = new Size(819, 156); |
| | | grpReceive.TabIndex = 30; |
| | | grpReceive.TabStop = false; |
| | | grpReceive.Text = "通讯记录"; |
| | |
| | | // txtReceiveMsg |
| | | // |
| | | txtReceiveMsg.Dock = DockStyle.Fill; |
| | | txtReceiveMsg.Location = new Point(3, 17); |
| | | txtReceiveMsg.Location = new Point(4, 21); |
| | | txtReceiveMsg.Margin = new Padding(4, 4, 4, 4); |
| | | txtReceiveMsg.Multiline = true; |
| | | txtReceiveMsg.Name = "txtReceiveMsg"; |
| | | txtReceiveMsg.ReadOnly = true; |
| | | txtReceiveMsg.ScrollBars = ScrollBars.Both; |
| | | txtReceiveMsg.Size = new Size(649, 106); |
| | | txtReceiveMsg.Size = new Size(811, 131); |
| | | txtReceiveMsg.TabIndex = 0; |
| | | // |
| | | // txtSendMsg |
| | | // |
| | | txtSendMsg.Dock = DockStyle.Fill; |
| | | txtSendMsg.Location = new Point(3, 123); |
| | | txtSendMsg.Location = new Point(4, 154); |
| | | txtSendMsg.Margin = new Padding(4, 4, 4, 4); |
| | | txtSendMsg.Name = "txtSendMsg"; |
| | | txtSendMsg.Size = new Size(655, 21); |
| | | txtSendMsg.Size = new Size(819, 24); |
| | | txtSendMsg.TabIndex = 29; |
| | | // |
| | | // grpSetting |
| | |
| | | grpSetting.Controls.Add(lblType); |
| | | grpSetting.Controls.Add(lblAddress); |
| | | grpSetting.Controls.Add(lblIP); |
| | | grpSetting.Controls.Add(cmbDataType); |
| | | grpSetting.Controls.Add(lblDataType); |
| | | grpSetting.Dock = DockStyle.Fill; |
| | | grpSetting.ForeColor = Color.CornflowerBlue; |
| | | grpSetting.Location = new Point(3, 3); |
| | | grpSetting.MinimumSize = new Size(261, 61); |
| | | grpSetting.Location = new Point(4, 4); |
| | | grpSetting.Margin = new Padding(4, 4, 4, 4); |
| | | grpSetting.MinimumSize = new Size(326, 76); |
| | | grpSetting.Name = "grpSetting"; |
| | | grpSetting.Size = new Size(655, 94); |
| | | grpSetting.Padding = new Padding(4, 4, 4, 4); |
| | | grpSetting.Size = new Size(819, 117); |
| | | grpSetting.TabIndex = 28; |
| | | grpSetting.TabStop = false; |
| | | grpSetting.Text = "通讯配置"; |
| | | // |
| | | // txtAddress |
| | | // |
| | | txtAddress.Location = new Point(251, 60); |
| | | txtAddress.Location = new Point(314, 75); |
| | | txtAddress.Margin = new Padding(4, 4, 4, 4); |
| | | txtAddress.Name = "txtAddress"; |
| | | txtAddress.Size = new Size(100, 21); |
| | | txtAddress.Size = new Size(124, 24); |
| | | txtAddress.TabIndex = 9; |
| | | txtAddress.TextChanged += txtAddress_TextChanged; |
| | | // |
| | |
| | | // |
| | | cmbType.DropDownStyle = ComboBoxStyle.DropDownList; |
| | | cmbType.FormattingEnabled = true; |
| | | cmbType.Location = new Point(251, 23); |
| | | cmbType.Location = new Point(314, 29); |
| | | cmbType.Margin = new Padding(4, 4, 4, 4); |
| | | cmbType.Name = "cmbType"; |
| | | cmbType.Size = new Size(100, 23); |
| | | cmbType.Size = new Size(124, 26); |
| | | cmbType.TabIndex = 8; |
| | | // |
| | | // txtIP |
| | | // |
| | | txtIP.Location = new Point(79, 22); |
| | | txtIP.Location = new Point(99, 28); |
| | | txtIP.Margin = new Padding(4, 4, 4, 4); |
| | | txtIP.Name = "txtIP"; |
| | | txtIP.Size = new Size(100, 21); |
| | | txtIP.Size = new Size(124, 24); |
| | | txtIP.TabIndex = 7; |
| | | // |
| | | // txtPort |
| | | // |
| | | txtPort.Location = new Point(79, 60); |
| | | txtPort.Location = new Point(99, 75); |
| | | txtPort.Margin = new Padding(4, 4, 4, 4); |
| | | txtPort.Name = "txtPort"; |
| | | txtPort.Size = new Size(100, 21); |
| | | txtPort.Size = new Size(124, 24); |
| | | txtPort.TabIndex = 6; |
| | | // |
| | | // lblPort |
| | | // |
| | | lblPort.AutoSize = true; |
| | | lblPort.Location = new Point(13, 63); |
| | | lblPort.Location = new Point(16, 79); |
| | | lblPort.Margin = new Padding(4, 0, 4, 0); |
| | | lblPort.Name = "lblPort"; |
| | | lblPort.Size = new Size(31, 15); |
| | | lblPort.Size = new Size(38, 18); |
| | | lblPort.TabIndex = 4; |
| | | lblPort.Text = "端口"; |
| | | // |
| | | // cmbIP |
| | | // |
| | | cmbIP.FormattingEnabled = true; |
| | | cmbIP.Location = new Point(79, 21); |
| | | cmbIP.Location = new Point(99, 26); |
| | | cmbIP.Margin = new Padding(4, 4, 4, 4); |
| | | cmbIP.Name = "cmbIP"; |
| | | cmbIP.Size = new Size(100, 23); |
| | | cmbIP.Size = new Size(124, 26); |
| | | cmbIP.TabIndex = 1; |
| | | // |
| | | // lblType |
| | | // |
| | | lblType.AutoSize = true; |
| | | lblType.Location = new Point(205, 26); |
| | | lblType.Location = new Point(256, 32); |
| | | lblType.Margin = new Padding(4, 0, 4, 0); |
| | | lblType.Name = "lblType"; |
| | | lblType.Size = new Size(31, 15); |
| | | lblType.Size = new Size(38, 18); |
| | | lblType.TabIndex = 0; |
| | | lblType.Text = "型号"; |
| | | // |
| | | // lblAddress |
| | | // |
| | | lblAddress.AutoSize = true; |
| | | lblAddress.Location = new Point(205, 63); |
| | | lblAddress.Location = new Point(256, 79); |
| | | lblAddress.Margin = new Padding(4, 0, 4, 0); |
| | | lblAddress.Name = "lblAddress"; |
| | | lblAddress.Size = new Size(31, 15); |
| | | lblAddress.Size = new Size(38, 18); |
| | | lblAddress.TabIndex = 0; |
| | | lblAddress.Text = "地址"; |
| | | // |
| | | // lblIP |
| | | // |
| | | lblIP.AutoSize = true; |
| | | lblIP.Location = new Point(13, 26); |
| | | lblIP.Location = new Point(16, 32); |
| | | lblIP.Margin = new Padding(4, 0, 4, 0); |
| | | lblIP.Name = "lblIP"; |
| | | lblIP.Size = new Size(31, 15); |
| | | lblIP.Size = new Size(38, 18); |
| | | lblIP.TabIndex = 0; |
| | | lblIP.Text = "地址"; |
| | | // |
| | | // cmbDataType |
| | | // |
| | | cmbDataType.DropDownStyle = ComboBoxStyle.DropDownList; |
| | | cmbDataType.FormattingEnabled = true; |
| | | cmbDataType.Location = new Point(525, 75); |
| | | cmbDataType.Margin = new Padding(4, 4, 4, 4); |
| | | cmbDataType.Name = "cmbDataType"; |
| | | cmbDataType.Size = new Size(124, 26); |
| | | cmbDataType.TabIndex = 11; |
| | | cmbDataType.SelectedIndexChanged += cmbDataType_SelectedIndexChanged; |
| | | // |
| | | // lblDataType |
| | | // |
| | | lblDataType.AutoSize = true; |
| | | lblDataType.Location = new Point(462, 79); |
| | | lblDataType.Margin = new Padding(4, 0, 4, 0); |
| | | lblDataType.Name = "lblDataType"; |
| | | lblDataType.Size = new Size(38, 18); |
| | | lblDataType.TabIndex = 10; |
| | | lblDataType.Text = "类型"; |
| | | // |
| | | // tableLayoutPanel2 |
| | | // |
| | | tableLayoutPanel2.ColumnCount = 3; |
| | | tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F)); |
| | | tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 80F)); |
| | | tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F)); |
| | | tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 100F)); |
| | | tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); |
| | | tableLayoutPanel2.Controls.Add(btnRuleSend, 1, 0); |
| | | tableLayoutPanel2.Controls.Add(btnSend, 0, 0); |
| | | tableLayoutPanel2.Dock = DockStyle.Fill; |
| | | tableLayoutPanel2.Location = new Point(3, 153); |
| | | tableLayoutPanel2.Location = new Point(4, 192); |
| | | tableLayoutPanel2.Margin = new Padding(4, 4, 4, 4); |
| | | tableLayoutPanel2.Name = "tableLayoutPanel2"; |
| | | tableLayoutPanel2.RowCount = 1; |
| | | tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); |
| | | tableLayoutPanel2.Size = new Size(655, 34); |
| | | tableLayoutPanel2.Size = new Size(819, 42); |
| | | tableLayoutPanel2.TabIndex = 27; |
| | | // |
| | | // btnRuleSend |
| | | // |
| | | btnRuleSend.Dock = DockStyle.Fill; |
| | | btnRuleSend.ForeColor = Color.CornflowerBlue; |
| | | btnRuleSend.Location = new Point(83, 3); |
| | | btnRuleSend.Location = new Point(104, 4); |
| | | btnRuleSend.Margin = new Padding(4, 4, 4, 4); |
| | | btnRuleSend.Name = "btnRuleSend"; |
| | | btnRuleSend.Size = new Size(74, 28); |
| | | btnRuleSend.Size = new Size(92, 34); |
| | | btnRuleSend.TabIndex = 14; |
| | | btnRuleSend.Text = "校验发送"; |
| | | btnRuleSend.UseVisualStyleBackColor = true; |
| | |
| | | // |
| | | btnSend.Dock = DockStyle.Fill; |
| | | btnSend.ForeColor = Color.CornflowerBlue; |
| | | btnSend.Location = new Point(3, 3); |
| | | btnSend.Location = new Point(4, 4); |
| | | btnSend.Margin = new Padding(4, 4, 4, 4); |
| | | btnSend.Name = "btnSend"; |
| | | btnSend.Size = new Size(74, 28); |
| | | btnSend.Size = new Size(92, 34); |
| | | btnSend.TabIndex = 12; |
| | | btnSend.Text = "发送"; |
| | | btnSend.UseVisualStyleBackColor = true; |
| | |
| | | themeForm_Communicator.Font = new Font("Microsoft Sans Serif", 9F); |
| | | themeForm_Communicator.Image = (Image)resources.GetObject("themeForm_Communicator.Image"); |
| | | themeForm_Communicator.Location = new Point(0, 0); |
| | | themeForm_Communicator.Margin = new Padding(4, 4, 4, 4); |
| | | themeForm_Communicator.Name = "themeForm_Communicator"; |
| | | themeForm_Communicator.Padding = new Padding(10, 70, 10, 9); |
| | | themeForm_Communicator.Padding = new Padding(12, 88, 12, 11); |
| | | themeForm_Communicator.RoundCorners = true; |
| | | themeForm_Communicator.Sizable = true; |
| | | themeForm_Communicator.Size = new Size(681, 401); |
| | | themeForm_Communicator.Size = new Size(851, 501); |
| | | themeForm_Communicator.SmartBounds = true; |
| | | themeForm_Communicator.StartPosition = FormStartPosition.WindowsDefaultLocation; |
| | | themeForm_Communicator.TabIndex = 27; |
| | |
| | | controlBox1.EnableMaximizeButton = true; |
| | | controlBox1.EnableMinimizeButton = true; |
| | | controlBox1.ForeColor = Color.FromArgb(155, 155, 155); |
| | | controlBox1.Location = new Point(581, 18); |
| | | controlBox1.Location = new Point(726, 22); |
| | | controlBox1.Margin = new Padding(4, 4, 4, 4); |
| | | controlBox1.MaximizeHoverColor = Color.FromArgb(74, 74, 74); |
| | | controlBox1.MinimizeHoverColor = Color.FromArgb(63, 63, 65); |
| | | controlBox1.Name = "controlBox1"; |
| | |
| | | // |
| | | panel_CommunicatorForm.Controls.Add(tableLayoutPanel1); |
| | | panel_CommunicatorForm.Dock = DockStyle.Fill; |
| | | panel_CommunicatorForm.Location = new Point(10, 70); |
| | | panel_CommunicatorForm.Location = new Point(12, 88); |
| | | panel_CommunicatorForm.Margin = new Padding(4, 4, 4, 4); |
| | | panel_CommunicatorForm.Name = "panel_CommunicatorForm"; |
| | | panel_CommunicatorForm.Size = new Size(661, 322); |
| | | panel_CommunicatorForm.Size = new Size(827, 402); |
| | | panel_CommunicatorForm.TabIndex = 27; |
| | | // |
| | | // CommunicatorForm |
| | | // |
| | | AutoScaleDimensions = new SizeF(96F, 96F); |
| | | AutoScaleDimensions = new SizeF(120F, 120F); |
| | | AutoScaleMode = AutoScaleMode.Dpi; |
| | | ClientSize = new Size(681, 401); |
| | | ClientSize = new Size(851, 501); |
| | | Controls.Add(themeForm_Communicator); |
| | | FormBorderStyle = FormBorderStyle.None; |
| | | MinimumSize = new Size(261, 61); |
| | | Margin = new Padding(4, 4, 4, 4); |
| | | MinimumSize = new Size(326, 76); |
| | | Name = "CommunicatorForm"; |
| | | Text = "通讯设置"; |
| | | TransparencyKey = Color.Fuchsia; |
| | |
| | | private ComboBox cmbType; |
| | | private Label lblAddress; |
| | | private TextBox txtAddress; |
| | | private Label lblDataType; |
| | | private ComboBox cmbDataType; |
| | | } |
| | | } |
| | |
| | | cmbIP.Enabled = false; |
| | | txtIP.Enabled = false; |
| | | txtPort.Enabled = false; |
| | | cmbDataType.Enabled = false; |
| | | |
| | | |
| | | lblType.Visible = false; |
| | | lblAddress.Visible = false; |
| | | cmbType.Visible = false; |
| | | txtAddress.Visible = false; |
| | | lblDataType.Visible = false; |
| | | cmbDataType.Visible = false; |
| | | |
| | | |
| | | this.Text = name; |
| | |
| | | lblAddress.Visible = false; |
| | | cmbType.Visible = false; |
| | | txtAddress.Visible = false; |
| | | lblDataType.Visible = false; |
| | | cmbDataType.Visible = false; |
| | | |
| | | lblIP.Text = "COM口"; |
| | | lblPort.Text = "波特率"; |
| | |
| | | else if (communicator is TCPClient || communicator is TCPServer) |
| | | { |
| | | txtIP.Text = communicator.CommunicatorConnections["地址"]?.ToString(); |
| | | txtPort.SelectedText = communicator.CommunicatorConnections["端口"]?.ToString(); |
| | | txtPort.Text = communicator.CommunicatorConnections["端口"]?.ToString(); |
| | | txtIP.Visible = true; |
| | | cmbIP.Visible = false; |
| | | |
| | |
| | | lblAddress.Visible = false; |
| | | cmbType.Visible = false; |
| | | txtAddress.Visible = false; |
| | | lblDataType.Visible = false; |
| | | cmbDataType.Visible = false; |
| | | |
| | | lblIP.Text = "地址"; |
| | | lblPort.Text = "端口"; |
| | |
| | | { |
| | | txtAddress.Text = communicator.CommunicatorConnections["变量地址"]?.ToString(); |
| | | } |
| | | |
| | | // 初始化数据类型 |
| | | cmbDataType.Items.Clear(); |
| | | cmbDataType.Items.AddRange(new string[] { "String", "Bool", "Byte", "Int", "DInt", "Real", "Double", "Word", "DWord" }); |
| | | if (communicator.CommunicatorConnections.Contains("数据类型")) |
| | | cmbDataType.Text = communicator.CommunicatorConnections["数据类型"].ToString(); |
| | | else |
| | | cmbDataType.Text = "String"; |
| | | |
| | | txtIP.Visible = true; |
| | | cmbIP.Visible = false; |
| | | this.btnRuleSend.Visible = false; |
| | |
| | | lblAddress.Visible = true; |
| | | cmbType.Visible = true; |
| | | txtAddress.Visible = true; |
| | | lblDataType.Visible = true; |
| | | cmbDataType.Visible = true; |
| | | cmbDataType.Enabled = true; // 启用数据类型选择 |
| | | |
| | | lblIP.Text = "IP"; |
| | | lblPort.Text = "槽"; |
| | |
| | | this.communicator = communicator; |
| | | //加载回调函数 |
| | | Subscribe(); |
| | | } |
| | | |
| | | private void cmbDataType_SelectedIndexChanged(object sender, EventArgs e) |
| | | { |
| | | if (communicator != null) |
| | | { |
| | | communicator.CommunicatorConnections.Add("数据类型", cmbDataType.Text); |
| | | communicatorChanged(communicator); |
| | | } |
| | | } |
| | | |
| | | private void CommunicatorForm_FormClosing(object sender, FormClosingEventArgs e) => Unsubscribe(); |
| | |
| | | } |
| | | } |
| | | |
| | | 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) |
| | |
| | | |
| | | if (communicator.SendMessage(txtSendMsg.Text)) |
| | | ShowSendMsg(txtSendMsg.Text); |
| | | else |
| | | ShowLogMsg(communicator.Msg); |
| | | } |
| | | |
| | | private void btnRuleSend_Click(object sender, EventArgs e) |
| | |
| | | |
| | | if (communicator.SendMessage(SendMsg)) |
| | | ShowSendMsg(SendMsg); |
| | | else |
| | | ShowLogMsg(communicator.Msg); |
| | | } |
| | | |
| | | private void txtAddress_TextChanged(object sender, EventArgs e) |
| | | { |
| | | if (communicator != null && !communicator.CommunicatorConnections.Contains("变量地址")) |
| | | if (communicator != null) |
| | | { |
| | | communicator.CommunicatorConnections.Add("变量地址", txtAddress.Text); |
| | | } |
| | | else if (communicator != null) |
| | | { |
| | | communicator.CommunicatorConnections["变量地址"] = txtAddress.Text; |
| | | communicatorChanged(communicator); |
| | | } |
| | | } |
| | |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT)) |
| | | return; |
| | | |
| | | string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}"; |
| | | string DataType = item.Value.CommunicatorConnections.Contains("数据类型") ? |
| | | item.Value.CommunicatorConnections["数据类型"].ToString() : "String"; |
| | | string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT} [{DataType}]"; |
| | | |
| | | UserItem flow = new UserItem(new string[] { "测试", "刷新", "移除", "重命名" }); |
| | | //flow.SetDPIScale(); |
| | |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT)) |
| | | return; |
| | | |
| | | string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT}"; |
| | | string DataType = communicator.CommunicatorConnections.Contains("数据类型") ? |
| | | communicator.CommunicatorConnections["数据类型"].ToString() : "String"; |
| | | string CommunicatorConnectionString = $"({ClassName}){IP}:{PORT} [{DataType}]"; |
| | | |
| | | GlobalVar.dicCommunicators.TryAdd(Name, communicator); |
| | | communicator.CommunicatorName = Name; |
| | |
| | | |
| | | private void CommunicatorFForm_CommunicatorChanged(BaseCommunicator communicator) |
| | | { |
| | | if (this.InvokeRequired) |
| | | { |
| | | this.Invoke(new Action<BaseCommunicator>(CommunicatorFForm_CommunicatorChanged), communicator); |
| | | return; |
| | | } |
| | | |
| | | for (int i = 0; i < uiFlowLayoutPanel1.Controls.Count; i++) |
| | | { |
| | | if (uiFlowLayoutPanel1.Controls[i] is UserItem flow && flow.Name == communicator.CommunicatorName) |
| | | { |
| | | string ClassName = communicator.GetType().Name; |
| | | string IP = communicator.CommunicatorConnections["地址"].ToString(); |
| | | string PORT = communicator.CommunicatorConnections["端口"].ToString(); |
| | | string DataType = communicator.CommunicatorConnections.Contains("数据类型") ? |
| | | communicator.CommunicatorConnections["数据类型"].ToString() : "String"; |
| | | |
| | | flow.Text = $"({ClassName}){IP}:{PORT} [{DataType}]"; |
| | | flow.Refresh(); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 移除通讯口 |
| | |
| | | labelStartTime = new Label(); |
| | | dataGridViewHD = new DataGridView(); |
| | | tableLayoutPanel4 = new TableLayoutPanel(); |
| | | hopeButton1 = new ReaLTaiizor.Controls.HopeButton(); |
| | | hopeButton2 = new ReaLTaiizor.Controls.HopeButton(); |
| | | btnHisDataFind = new ReaLTaiizor.Controls.HopeButton(); |
| | | btnHisDataExport = new ReaLTaiizor.Controls.HopeButton(); |
| | | grpHisData.SuspendLayout(); |
| | | tableLayoutPanel1.SuspendLayout(); |
| | | tableLayoutPanel2.SuspendLayout(); |
| | |
| | | tableLayoutPanel4.ColumnCount = 2; |
| | | tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); |
| | | tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); |
| | | tableLayoutPanel4.Controls.Add(hopeButton1, 0, 0); |
| | | tableLayoutPanel4.Controls.Add(hopeButton2, 1, 0); |
| | | tableLayoutPanel4.Controls.Add(btnHisDataFind, 0, 0); |
| | | tableLayoutPanel4.Controls.Add(btnHisDataExport, 1, 0); |
| | | tableLayoutPanel4.Location = new Point(657, 509); |
| | | tableLayoutPanel4.Name = "tableLayoutPanel4"; |
| | | tableLayoutPanel4.RowCount = 1; |
| | |
| | | tableLayoutPanel4.Size = new Size(200, 39); |
| | | tableLayoutPanel4.TabIndex = 1; |
| | | // |
| | | // hopeButton1 |
| | | // btnHisDataFind |
| | | // |
| | | hopeButton1.BorderColor = Color.FromArgb(220, 223, 230); |
| | | hopeButton1.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary; |
| | | hopeButton1.DangerColor = Color.FromArgb(245, 108, 108); |
| | | hopeButton1.DefaultColor = Color.FromArgb(255, 255, 255); |
| | | hopeButton1.Font = new Font("Segoe UI", 12F); |
| | | hopeButton1.HoverTextColor = Color.FromArgb(48, 49, 51); |
| | | hopeButton1.InfoColor = Color.FromArgb(144, 147, 153); |
| | | hopeButton1.Location = new Point(3, 3); |
| | | hopeButton1.Name = "hopeButton1"; |
| | | hopeButton1.PrimaryColor = Color.FromArgb(64, 158, 255); |
| | | hopeButton1.Size = new Size(94, 33); |
| | | hopeButton1.SuccessColor = Color.FromArgb(103, 194, 58); |
| | | hopeButton1.TabIndex = 0; |
| | | hopeButton1.Text = "查询"; |
| | | hopeButton1.TextColor = Color.White; |
| | | hopeButton1.WarningColor = Color.FromArgb(230, 162, 60); |
| | | btnHisDataFind.BorderColor = Color.FromArgb(220, 223, 230); |
| | | btnHisDataFind.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary; |
| | | btnHisDataFind.DangerColor = Color.FromArgb(245, 108, 108); |
| | | btnHisDataFind.DefaultColor = Color.FromArgb(255, 255, 255); |
| | | btnHisDataFind.Font = new Font("Segoe UI", 12F); |
| | | btnHisDataFind.HoverTextColor = Color.FromArgb(48, 49, 51); |
| | | btnHisDataFind.InfoColor = Color.FromArgb(144, 147, 153); |
| | | btnHisDataFind.Location = new Point(3, 3); |
| | | btnHisDataFind.Name = "btnHisDataFind"; |
| | | btnHisDataFind.PrimaryColor = Color.FromArgb(64, 158, 255); |
| | | btnHisDataFind.Size = new Size(94, 33); |
| | | btnHisDataFind.SuccessColor = Color.FromArgb(103, 194, 58); |
| | | btnHisDataFind.TabIndex = 0; |
| | | btnHisDataFind.Text = "查询"; |
| | | btnHisDataFind.TextColor = Color.White; |
| | | btnHisDataFind.WarningColor = Color.FromArgb(230, 162, 60); |
| | | // |
| | | // hopeButton2 |
| | | // btnHisDataExport |
| | | // |
| | | hopeButton2.BorderColor = Color.FromArgb(220, 223, 230); |
| | | hopeButton2.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary; |
| | | hopeButton2.DangerColor = Color.FromArgb(245, 108, 108); |
| | | hopeButton2.DefaultColor = Color.FromArgb(255, 255, 255); |
| | | hopeButton2.Font = new Font("Segoe UI", 12F); |
| | | hopeButton2.HoverTextColor = Color.FromArgb(48, 49, 51); |
| | | hopeButton2.InfoColor = Color.FromArgb(144, 147, 153); |
| | | hopeButton2.Location = new Point(103, 3); |
| | | hopeButton2.Name = "hopeButton2"; |
| | | hopeButton2.PrimaryColor = Color.FromArgb(64, 158, 255); |
| | | hopeButton2.Size = new Size(94, 33); |
| | | hopeButton2.SuccessColor = Color.FromArgb(103, 194, 58); |
| | | hopeButton2.TabIndex = 1; |
| | | hopeButton2.Text = "导出"; |
| | | hopeButton2.TextColor = Color.White; |
| | | hopeButton2.WarningColor = Color.FromArgb(230, 162, 60); |
| | | btnHisDataExport.BorderColor = Color.FromArgb(220, 223, 230); |
| | | btnHisDataExport.ButtonType = ReaLTaiizor.Util.HopeButtonType.Primary; |
| | | btnHisDataExport.DangerColor = Color.FromArgb(245, 108, 108); |
| | | btnHisDataExport.DefaultColor = Color.FromArgb(255, 255, 255); |
| | | btnHisDataExport.Font = new Font("Segoe UI", 12F); |
| | | btnHisDataExport.HoverTextColor = Color.FromArgb(48, 49, 51); |
| | | btnHisDataExport.InfoColor = Color.FromArgb(144, 147, 153); |
| | | btnHisDataExport.Location = new Point(103, 3); |
| | | btnHisDataExport.Name = "btnHisDataExport"; |
| | | btnHisDataExport.PrimaryColor = Color.FromArgb(64, 158, 255); |
| | | btnHisDataExport.Size = new Size(94, 33); |
| | | btnHisDataExport.SuccessColor = Color.FromArgb(103, 194, 58); |
| | | btnHisDataExport.TabIndex = 1; |
| | | btnHisDataExport.Text = "导出"; |
| | | btnHisDataExport.TextColor = Color.White; |
| | | btnHisDataExport.WarningColor = Color.FromArgb(230, 162, 60); |
| | | btnHisDataExport.Click += btnHisDataExport_Click; |
| | | // |
| | | // HistoricalDataEditPage |
| | | // |
| | |
| | | private TableLayoutPanel tableLayoutPanel3; |
| | | private DataGridView dataGridViewHD; |
| | | private TableLayoutPanel tableLayoutPanel4; |
| | | private ReaLTaiizor.Controls.HopeButton hopeButton1; |
| | | private ReaLTaiizor.Controls.HopeButton hopeButton2; |
| | | private ReaLTaiizor.Controls.HopeButton btnHisDataFind; |
| | | private ReaLTaiizor.Controls.HopeButton btnHisDataExport; |
| | | private TableLayoutPanel tableLayoutPanel5; |
| | | private Label labelSearchBasis; |
| | | private TableLayoutPanel tableLayoutPanelSN; |
| | |
| | | } |
| | | |
| | | // 设置列标题 |
| | | dataGridViewHD.Columns[0].Name = "SN号"; |
| | | dataGridViewHD.Columns[0].Name = "SN号"; |
| | | dataGridViewHD.Columns[1].Name = "时间"; |
| | | dataGridViewHD.Columns[2].Name = "NG类"; |
| | | dataGridViewHD.Columns[3].Name = "缺陷大小"; |
| | |
| | | { |
| | | dateTimePickerEnd.MinDate = dateTimePickerStart.Value; |
| | | } |
| | | |
| | | private void btnHisDataExport_Click(object sender, EventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | public void SaveToCSV(string filePath, int rowIndex) |
| | | { |
| | | // 使用 StreamWriter 来写入文件 |
| | | using (StreamWriter writer = new StreamWriter(filePath)) |
| | | { |
| | | DataGridViewRow row = dataGridViewHD.Rows[rowIndex]; |
| | | |
| | | int rowCount = 10;//10改为采集次数 |
| | | |
| | | writer.WriteLine("SN号, 时间, NG类, 缺陷大小"); |
| | | |
| | | // 遍历每一行数据 |
| | | for (int i = 0; i < rowCount; i++) |
| | | { |
| | | int batchSize = 4; |
| | | |
| | | // 写入这一批次的每一列数据 |
| | | for (int k = 0; k < batchSize; k++) |
| | | { |
| | | writer.Write($"{row.Cells[k].Value}"); |
| | | |
| | | // 在元素之间添加逗号,除非这是最后一个元素 |
| | | if (k < batchSize - 1) |
| | | { |
| | | writer.Write(","); |
| | | } |
| | | } |
| | | |
| | | // 写入完一行后,换行 |
| | | writer.WriteLine(); |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | btnEdit.Text = "修改"; |
| | | btnEdit.TextColor = Color.White; |
| | | btnEdit.WarningColor = Color.FromArgb(230, 162, 60); |
| | | btnEdit.Click += btnEdit_Click; |
| | | // |
| | | // btnFind |
| | | // |
| | |
| | | InitializeComboBox(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 表格初始化 |
| | | /// </summary> |
| | | private void InitializeDataGridView() |
| | | { |
| | | // 设置DataGridView列宽 |
| | | dataGridViewUM.ColumnCount = 5; |
| | | dataGridViewUM.ColumnCount = 4; |
| | | |
| | | int totalWidth = dataGridViewUM.ClientSize.Width; |
| | | int columnCount = dataGridViewUM.ColumnCount; |
| | |
| | | |
| | | // 设置列标题 |
| | | dataGridViewUM.Columns[0].Name = "用户名"; |
| | | dataGridViewUM.Columns[1].Name = "密码"; |
| | | dataGridViewUM.Columns[2].Name = "姓名"; |
| | | dataGridViewUM.Columns[3].Name = "工号"; |
| | | dataGridViewUM.Columns[4].Name = "权限"; |
| | | //dataGridViewUM.Columns[1].Name = "密码"; |
| | | dataGridViewUM.Columns[1].Name = "姓名"; |
| | | dataGridViewUM.Columns[2].Name = "工号"; |
| | | dataGridViewUM.Columns[3].Name = "权限"; |
| | | |
| | | dataGridViewUM.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; |
| | | |
| | |
| | | dataGridViewUM.RowHeadersVisible = true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 权限下拉框初始化 |
| | | /// </summary> |
| | | private void InitializeComboBox() |
| | | { |
| | | // 添加权限选项 |
| | |
| | | textBoxPassword.Clear(); |
| | | textBoxName.Clear(); |
| | | textBoxEmployeeID.Clear(); |
| | | comboBoxPermission.SelectedIndex = 1; |
| | | comboBoxPermission.SelectedIndex = 0; |
| | | textBoxUsername.Focus(); // 将焦点设置回用户名输入框 |
| | | } |
| | | private void btnAdd_Click(object sender, EventArgs e) |
| | |
| | | string[] row = new string[] |
| | | { |
| | | textBoxUsername.Text, |
| | | textBoxPassword.Text, // 实际应用中密码应该加密 |
| | | //textBoxPassword.Text, // 实际应用中密码应该加密 |
| | | textBoxName.Text, |
| | | textBoxEmployeeID.Text, |
| | | comboBoxPermission.SelectedItem.ToString() |
| | |
| | | MessageBoxButtons.OK, MessageBoxIcon.Information); |
| | | } |
| | | } |
| | | private int editingRowIndex = -1; |
| | | private bool isEditingMode = false; |
| | | private string originalButtonText = "修改"; |
| | | private void btnEdit_Click(object sender, EventArgs e) |
| | | { |
| | | // 单元格可编辑 |
| | | //dataGridViewUM.ReadOnly = false; |
| | | // 第一次点击:进入修改模式 |
| | | if (!isEditingMode) |
| | | { |
| | | // 检查是否选择了行 |
| | | if (dataGridViewUM.SelectedRows.Count == 0) |
| | | { |
| | | MessageBox.Show("请先选择要修改的行!", "提示", |
| | | MessageBoxButtons.OK, MessageBoxIcon.Warning); |
| | | return; |
| | | } |
| | | |
| | | // 获取选中的行索引 |
| | | editingRowIndex = dataGridViewUM.SelectedRows[0].Index; |
| | | |
| | | // 将选中行的数据填充到TextBox中 |
| | | FillFormWithRowData(editingRowIndex); |
| | | |
| | | // 更改按钮文本 |
| | | btnEdit.Text = "完成"; |
| | | |
| | | // 进入编辑模式 |
| | | isEditingMode = true; |
| | | |
| | | // 禁用添加按钮(可选) |
| | | btnAdd.Enabled = false; |
| | | |
| | | // 设置焦点到用户名输入框 |
| | | textBoxUsername.Focus(); |
| | | |
| | | // 高亮显示正在编辑的行(可选) |
| | | dataGridViewUM.Rows[editingRowIndex].DefaultCellStyle.BackColor = Color.LightYellow; |
| | | } |
| | | // 第二次点击:保存修改 |
| | | else |
| | | { |
| | | // 验证输入 |
| | | if (string.IsNullOrWhiteSpace(textBoxUsername.Text) || |
| | | string.IsNullOrWhiteSpace(textBoxName.Text) || |
| | | string.IsNullOrWhiteSpace(textBoxEmployeeID.Text)) |
| | | { |
| | | MessageBox.Show("请填写所有必填字段!", "提示", |
| | | MessageBoxButtons.OK, MessageBoxIcon.Warning); |
| | | return; |
| | | } |
| | | |
| | | // 更新DataGridView中的行数据 |
| | | UpdateRowData(editingRowIndex); |
| | | |
| | | // 恢复按钮文本 |
| | | btnEdit.Text = originalButtonText; |
| | | |
| | | // 退出编辑模式 |
| | | isEditingMode = false; |
| | | editingRowIndex = -1; |
| | | |
| | | // 启用添加按钮(可选) |
| | | btnAdd.Enabled = true; |
| | | |
| | | // 恢复行颜色(可选) |
| | | dataGridViewUM.DefaultCellStyle.BackColor = Color.White; |
| | | |
| | | // 清空输入框 |
| | | ClearInputFields(); |
| | | |
| | | MessageBox.Show("修改完成!", "提示", |
| | | MessageBoxButtons.OK, MessageBoxIcon.Information); |
| | | } |
| | | } |
| | | |
| | | private void FillFormWithRowData(int rowIndex) |
| | | { |
| | | if (rowIndex >= 0 && rowIndex < dataGridViewUM.Rows.Count) |
| | | { |
| | | DataGridViewRow row = dataGridViewUM.Rows[rowIndex]; |
| | | |
| | | // 填充用户名 |
| | | if (row.Cells[0].Value != null) |
| | | textBoxUsername.Text = row.Cells[0].Value.ToString(); |
| | | else |
| | | textBoxUsername.Text = ""; |
| | | |
| | | // 填充姓名 |
| | | if (row.Cells[1].Value != null) |
| | | textBoxName.Text = row.Cells[1].Value.ToString(); |
| | | else |
| | | textBoxName.Text = ""; |
| | | |
| | | // 填充工号 |
| | | if (row.Cells[2].Value != null) |
| | | textBoxEmployeeID.Text = row.Cells[2].Value.ToString(); |
| | | else |
| | | textBoxEmployeeID.Text = ""; |
| | | |
| | | // 填充权限 |
| | | if (row.Cells[3].Value != null) |
| | | { |
| | | string permission = row.Cells[3].Value.ToString(); |
| | | int index = comboBoxPermission.FindString(permission); |
| | | if (index >= 0) |
| | | comboBoxPermission.SelectedIndex = index; |
| | | else |
| | | comboBoxPermission.SelectedIndex = 0; |
| | | } |
| | | else |
| | | { |
| | | comboBoxPermission.SelectedIndex = 0; |
| | | } |
| | | |
| | | // 密码框清空(通常不会显示密码) |
| | | textBoxPassword.Clear(); |
| | | // 如果需要修改密码,可以添加注释或占位符 |
| | | //textBoxPassword.PlaceholderText = "如需修改密码请填写"; |
| | | } |
| | | } |
| | | |
| | | private void UpdateRowData(int rowIndex) |
| | | { |
| | | if (rowIndex >= 0 && rowIndex < dataGridViewUM.Rows.Count) |
| | | { |
| | | DataGridViewRow row = dataGridViewUM.Rows[rowIndex]; |
| | | |
| | | // 更新用户名 |
| | | row.Cells[0].Value = textBoxUsername.Text; |
| | | |
| | | // 如果密码不为空,则更新密码(实际应用中应加密) |
| | | if (!string.IsNullOrWhiteSpace(textBoxPassword.Text)) |
| | | { |
| | | // 这里可以添加密码加密逻辑 |
| | | // row.Cells[1].Value = EncryptPassword(textBoxPassword.Text); |
| | | } |
| | | |
| | | // 更新姓名 |
| | | row.Cells[1].Value = textBoxName.Text; |
| | | |
| | | // 更新工号 |
| | | row.Cells[2].Value = textBoxEmployeeID.Text; |
| | | |
| | | // 更新权限 |
| | | row.Cells[3].Value = comboBoxPermission.SelectedItem.ToString(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | process.Load(ProcessPath); |
| | | process.strProcessName = ProcessName; |
| | | |
| | | //if (process is VisionProTool && Tool.ContainsChinese(ProcessName)) |
| | | // MessageBox.Show($"VisionPro工具不支持命名为中文:{ProcessName}", "异常"); |
| | | |
| | | if (process is ScriptTool script) |
| | | { |
| | | if (script.Params.Outputs.Count <= 0) |
| | |
| | | { |
| | | dicInputsMapping.TryAdd(name, new List<Tuple<string, string>>()); |
| | | dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs.Image", "")); |
| | | //dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs.Fixture", "")); |
| | | |
| | | foreach (var item in process.Params.Inputs) |
| | | dicInputsMapping[name].Add(new Tuple<string, string>(name + ".Inputs." + item.Name, "")); |
| | |
| | | { |
| | | dicOutputsMapping.TryAdd(name, new List<string>()); |
| | | dicOutputsMapping[name].Add(name + ".Outputs.Image"); |
| | | dicOutputsMapping[name].Add(name + ".Outputs.Record"); |
| | | //dicOutputsMapping[name].Add(name + ".Outputs.Record"); |
| | | dicOutputsMapping[name].Add(name + ".Outputs.Result"); |
| | | //dicOutputsMapping[name].Add(name + ".Outputs.Fixture"); |
| | | |
| | | foreach (var item in process.Params.Outputs) |
| | | dicOutputsMapping[name].Add(name + ".Outputs." + item.Name); |
| | |
| | | Assembly_LB_VisionProcessesDll = Assembly.Load(Assembly_LB_VisionProcessesBytes); |
| | | |
| | | GlobalVar.dicCommunicators.DictionaryChanged += CommunicatorsChanged; |
| | | GlobalVar.dicCameras.DictionaryChanged += CamerasChanged; |
| | | GlobalVar.dicProcesses.DictionaryChanged += ProcessRunBllChanged; |
| | | |
| | | //最开始就清空所有Tab页 |
| | |
| | | |
| | | private void CommunicatorsChanged(object? sender, DictionaryChangedEventArgs<string, BaseCommunicator> e) |
| | | { |
| | | |
| | | try |
| | | { |
| | | switch (e.ChangeType) |
| | | { |
| | | case DictionaryChangeType.Added: |
| | | e.NewValue.TriggerRunMessageReceived += TriggerRunMessageReceived; |
| | | LogInfo($"通讯口[{e.NewValue.CommunicatorName}]加载触发通讯", LogInfoType.INFO); |
| | | e.NewValue.CommunicatorName = e.NewKey; |
| | | break; |
| | | case DictionaryChangeType.Renamed: |
| | | string OldCommunicatorName = e.OldKey; |
| | | string NewCommunicatorName = e.NewKey; |
| | | LogInfo(string.Format("重命名通讯口名[{0}]修改为[{1}]", OldCommunicatorName, NewCommunicatorName), LogInfoType.INFO); |
| | | e.NewValue.CommunicatorName = NewCommunicatorName; |
| | | break; |
| | | case DictionaryChangeType.Removed: |
| | | if (e.OldValue != null && e.OldValue is BaseCommunicator) |
| | | e.OldValue.Disconnect(); |
| | | e.OldValue.TriggerRunMessageReceived -= TriggerRunMessageReceived; |
| | | LogInfo($"通讯口[{e.OldValue.CommunicatorName}]移除触发通讯", LogInfoType.INFO); |
| | | break; |
| | | } |
| | | } |
| | | catch { } |
| | | } |
| | | |
| | | private void LogInfo(string strLog, LogInfoType infoType) |
| | |
| | | } |
| | | } |
| | | |
| | | private void CamerasChanged(object sender, DictionaryChangedEventArgs<string, BaseCamera> e) |
| | | { |
| | | try |
| | | { |
| | | switch (e.ChangeType) |
| | | { |
| | | case DictionaryChangeType.Added: |
| | | e.NewValue.TriggerRunMessageReceived += TriggerRunMessageReceived; |
| | | LogInfo($"相机[{e.NewValue.SN}]加载触发通讯", LogInfoType.INFO); |
| | | e.NewValue.SN = e.NewKey; |
| | | break; |
| | | case DictionaryChangeType.Removed: |
| | | if (e.OldValue != null && e.OldValue is BaseCommunicator) |
| | | e.OldValue.CloseDevice(); |
| | | e.OldValue.TriggerRunMessageReceived -= TriggerRunMessageReceived; |
| | | LogInfo($"相机[{e.OldValue.SN}]移除触发通讯", LogInfoType.INFO); |
| | | break; |
| | | } |
| | | } |
| | | catch { } |
| | | } |
| | | |
| | | private void VisionForm_Load(object sender, EventArgs e) |
| | | { |
| | | XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config")); |
| | |
| | | if (!string.IsNullOrEmpty(CommunicatorAddress) && CommunicatorAddress.Contains("SiemensLBS7")) |
| | | { |
| | | // 定义正则表达式以提取协议、IP 地址和端口 |
| | | //1. \((.*?)\):\(和 \) 是用于匹配括号的转义字符。 |
| | | // (.*?) 是一个非贪婪的匹配,用来匹配类名(MyProcesses.Communicators.TCPServer 或 MyProcesses.Communicators.UARTPort)。 |
| | | //2. ([^:] +):匹配冒号之前的部分,即地址(127.0.0.1 或 COM5)。这里使用了[^:] 来匹配除了冒号之外的任意字符。 |
| | | //3. (\d +) :匹配端口号,确保它匹配一个或多个数字。 |
| | | |
| | | string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\]$"; |
| | | // 更新正则以支持可选的数据类型字段 |
| | | string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\](?:\[(?<DataType>[^]]+)\])?$"; |
| | | Match match = Regex.Match(CommunicatorAddress, pattern); |
| | | |
| | | if (match.Success) |
| | |
| | | string Slot = match.Groups["Slot"].Value; // "1111" |
| | | string CpuType= match.Groups["CpuType"].Value; |
| | | string PlcAddress = match.Groups["PlcAddress"].Value; |
| | | string DataType = match.Groups["DataType"].Success ? match.Groups["DataType"].Value : "String"; |
| | | |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Slot) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress)) |
| | | break; |
| | | |
| | |
| | | Communicator.CommunicatorConnections.Add("端口", Slot); |
| | | Communicator.CommunicatorConnections.Add("型号", CpuType); |
| | | Communicator.CommunicatorConnections.Add("变量地址", PlcAddress); |
| | | Communicator.CommunicatorConnections.Add("数据类型", DataType); |
| | | Communicator.CommunicatorName = CommunicatorName; |
| | | if (!Communicator.Connect()) |
| | | { |
| | |
| | | { |
| | | string CpuType = item.Value.CommunicatorConnections["型号"].ToString(); |
| | | string PlcAddress = item.Value.CommunicatorConnections["变量地址"].ToString(); |
| | | string DataType = item.Value.CommunicatorConnections.Contains("数据类型") ? |
| | | item.Value.CommunicatorConnections["数据类型"].ToString() : "String"; |
| | | |
| | | if (string.IsNullOrEmpty(ClassName) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(PORT) || string.IsNullOrEmpty(CpuType) || string.IsNullOrEmpty(PlcAddress)) |
| | | { |
| | | break; |
| | | } |
| | | string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}]"; |
| | | string CommunicatorConnectionString = $"({ClassName})[{IP}][{PORT}][{CpuType}][{PlcAddress}][{DataType}]"; |
| | | GlobalVar.allCommunicatorsConnectionString.TryAdd(item.Key, CommunicatorConnectionString); |
| | | } |
| | | else |
| | |
| | | await ExecuteNodeAsync(currentNode, ExecutionContext); |
| | | |
| | | // 防止死循环,运行时间超过60秒则强制终止 |
| | | if ((DateTime.Now - StartTime).TotalSeconds > 1000000000) |
| | | if ((DateTime.Now - StartTime).TotalSeconds > 10) |
| | | { |
| | | _cancellationTokenSource.Cancel(); |
| | | NodesMsg = $"执行所有节点超过10s"; |
| | |
| | | /// 相机名称 |
| | | /// </summary> |
| | | public string CameraName { get; set; } = string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 相机硬触发获取图像触发对应的检测流程 |
| | | /// </summary> |
| | | public Action<string, string> TriggerRunMessageReceived; |
| | | public CameraBrand Brand { get; set; } = CameraBrand.UNSUPPORTED; |
| | | |
| | | public bool isGrabbing = false; |
| | |
| | | using MVSDK_Net; |
| | | using HalconDotNet; |
| | | using LB_SmartVisionCommon; |
| | | using MVSDK_Net; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Diagnostics; |
| | |
| | | private Thread _callbackThread; // 回调处理线程 |
| | | private List<IMVDefine.IMV_Frame> _frameList; // 图像缓存列表 |
| | | private readonly object _frameLock = new object(); // 帧缓存锁 |
| | | private IMVDefine.IMV_EPixelType type = IMVDefine.IMV_EPixelType.gvspPixelMono8; |
| | | private IMVDefine.IMV_PixelConvertParam stPixelConvertParam = new IMVDefine.IMV_PixelConvertParam(); |
| | | |
| | | HObject Hobj = new HObject(); |
| | | IntPtr pTemp = IntPtr.Zero; |
| | | IntPtr pConvertDstBuffer = IntPtr.Zero; |
| | | int nConvertBufSize = 0; |
| | | |
| | | |
| | | private IMVDefine.IMV_FrameCallBack frameCallBack; |
| | | |
| | | // CopyMemory API声明 |
| | | [System.Runtime.InteropServices.DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")] |
| | |
| | | { |
| | | // 记录日志或抛出异常 |
| | | //throw new Exception($"枚举设备失败,错误码:{result}"); |
| | | Debug.WriteLine("枚举设备失败!"); |
| | | AsyncLogHelper.Error("枚举设备失败!"); |
| | | System.Diagnostics.Debug.WriteLine("枚举设备失败!"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // 记录错误日志 |
| | | System.Diagnostics.Debug.WriteLine($"获取相机列表失败:{ex.Message}"); |
| | | AsyncLogHelper.Error($"获取相机列表失败:{ex.Message}"); |
| | | throw; |
| | | } |
| | | |
| | |
| | | |
| | | if (cameraIndex == -1) |
| | | { |
| | | AsyncLogHelper.Error($"未找到序列号为 {SN} 的相机"); |
| | | throw new Exception($"未找到序列号为 {SN} 的相机"); |
| | | } |
| | | |
| | |
| | | int result = _camera.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByIndex, cameraIndex); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | AsyncLogHelper.Error($"创建设备句柄失败,错误码:{result}"); |
| | | throw new Exception($"创建设备句柄失败,错误码:{result}"); |
| | | } |
| | | _handleCreated = true; |
| | |
| | | result = _camera.IMV_Open(); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | AsyncLogHelper.Error($"打开相机失败,错误码:{result}"); |
| | | throw new Exception($"打开相机失败,错误码:{result}"); |
| | | } |
| | | |
| | |
| | | this.SN = SN; |
| | | isGrabbing = false; |
| | | |
| | | // 设置缓存个数为8 |
| | | _camera.IMV_SetBufferCount(8); |
| | | // 注册数据帧回调函数 |
| | | // Register data frame callback function |
| | | frameCallBack = onGetFrame; |
| | | int res = _camera.IMV_AttachGrabbing(frameCallBack, IntPtr.Zero); |
| | | if (res != IMVDefine.IMV_OK) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine("Attach grabbing failed! ErrorCode:[{0}]", res); |
| | | AsyncLogHelper.Error("Attach grabbing failed! ErrorCode:[{0}]" + res); |
| | | } |
| | | // 设置缓存个数为12 |
| | | _camera.IMV_SetBufferCount(12); |
| | | |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"初始化相机失败:{ex.Message}"); |
| | | AsyncLogHelper.Error($"初始化相机失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // 数据帧回调函数 |
| | | // Data frame callback function |
| | | private void onGetFrame(ref IMVDefine.IMV_Frame frame, IntPtr pUser) |
| | | { |
| | | if (frame.frameHandle == IntPtr.Zero) |
| | | { |
| | | AsyncLogHelper.Info(SN + "frame is NULL"); |
| | | return; |
| | | } |
| | | try |
| | | { |
| | | Bitmap bitmap = ConvertFrameToBitmap(frame); |
| | | // 释放帧数据 |
| | | // release frame |
| | | _camera.IMV_ReleaseFrame(ref frame); |
| | | Task.Factory.StartNew(() => |
| | | { |
| | | CallBackImg = (Bitmap)bitmap.Clone(); |
| | | if (CallBackImg == null) |
| | | { |
| | | return; |
| | | } |
| | | if (GetTriggerMode(out TriggerMode mode, out TriggerSource source)) |
| | | { |
| | | if (mode == TriggerMode.On && source != TriggerSource.Software) |
| | | TriggerRunMessageReceived?.Invoke(SN, source.ToString()); // 触发运行事件 |
| | | } |
| | | bitmap.Dispose(); |
| | | }); |
| | | } |
| | | catch { } |
| | | AsyncLogHelper.Info(SN + "Get frame blockId = {0}" + frame.frameInfo.blockId); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 图像是否为Mono格式 |
| | | /// </summary> |
| | | /// <param name="enType"></param> |
| | | /// <returns></returns> |
| | | private bool IsMonoPixelFormat(IMVDefine.IMV_EPixelType enType) |
| | | { |
| | | switch (enType) |
| | | { |
| | | case IMVDefine.IMV_EPixelType.gvspPixelMono8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelMono10: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelMono10Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelMono12: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelMono12Packed: |
| | | return true; |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 图像是否为彩色 |
| | | /// </summary> |
| | | /// <param name="enType"></param> |
| | | /// <returns></returns> |
| | | private bool IsColorPixelFormat(IMVDefine.IMV_EPixelType enType) |
| | | { |
| | | switch (enType) |
| | | { |
| | | case IMVDefine.IMV_EPixelType.gvspPixelRGB8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBGR8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelRGBA8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBGRA8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelYUV422_8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelYUV422_8_UYVY: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGR8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayRG8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGB8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayBG8: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGB10: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGB10Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayBG10: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayBG10Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayRG10: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayRG10Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGR10: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGR10Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGB12: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGB12Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayBG12: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayBG12Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayRG12: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayRG12Packed: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGR12: |
| | | case IMVDefine.IMV_EPixelType.gvspPixelBayGR12Packed: |
| | | return true; |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 关闭相机设备 |
| | |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"关闭相机失败,错误码:{result}"); |
| | | AsyncLogHelper.Info(SN + $"关闭相机失败,错误码:{result}"); |
| | | } |
| | | } |
| | | |
| | |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"关闭相机失败:{ex.Message}"); |
| | | AsyncLogHelper.Info(SN + $"关闭相机失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | // 停止现有采集 |
| | |
| | | int result = _camera.IMV_StartGrabbing(); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"启动采集失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"启动采集失败,错误码:{result}"); |
| | | throw new Exception(SN + $"启动采集失败,错误码:{result}"); |
| | | } |
| | | |
| | | _isGrabbing = true; |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"启动采集失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"启动采集失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"启动采集失败:{ex.Message}"); |
| | | _isGrabbing = false; |
| | | isGrabbing = false; |
| | | return false; |
| | |
| | | int result = _camera.IMV_StopGrabbing(); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"停止采集失败,错误码:{result}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"停止采集失败,错误码:{result}"); |
| | | AsyncLogHelper.Info(SN + $"停止采集失败,错误码:{result}"); |
| | | } |
| | | |
| | | _isGrabbing = false; |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"停止采集失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"停止采集失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"停止采集失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | int result = _camera.IMV_ExecuteCommandFeature("TriggerSoftware"); |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"软触发失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"软触发失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"软触发失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | // 设置触发模式 |
| | |
| | | int result = _camera.IMV_SetEnumFeatureSymbol("TriggerMode", triggerMode); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"设置触发模式失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"设置触发模式失败,错误码:{result}"); |
| | | throw new Exception(SN + $"设置触发模式失败,错误码:{result}"); |
| | | } |
| | | |
| | | // 设置触发源 |
| | |
| | | result = _camera.IMV_SetEnumFeatureSymbol("TriggerSource", triggerSource); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"设置触发源失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"设置触发源失败,错误码:{result}"); |
| | | throw new Exception(SN + $"设置触发源失败,错误码:{result}"); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置触发模式失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置触发模式失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置触发模式失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | // 获取触发模式 |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取触发模式失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取触发模式失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取触发模式失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | // 验证曝光时间范围 |
| | |
| | | int result = _camera.IMV_GetDoubleFeatureMin("ExposureTime", ref minExp); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"获取曝光时间最小值失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"获取曝光时间最小值失败,错误码:{result}"); |
| | | throw new Exception(SN + $"获取曝光时间最小值失败,错误码:{result}"); |
| | | } |
| | | |
| | | result = _camera.IMV_GetDoubleFeatureMax("ExposureTime", ref maxExp); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"获取曝光时间最大值失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"获取曝光时间最大值失败,错误码:{result}"); |
| | | throw new Exception(SN + $"获取曝光时间最大值失败,错误码:{result}"); |
| | | } |
| | | |
| | | if (value < minExp || value > maxExp) |
| | | { |
| | | throw new Exception($"曝光时间超出范围,有效范围:{minExp} - {maxExp}"); |
| | | AsyncLogHelper.Error(SN + $"曝光时间超出范围,有效范围:{minExp} - {maxExp}"); |
| | | throw new Exception(SN + $"曝光时间超出范围,有效范围:{minExp} - {maxExp}"); |
| | | } |
| | | |
| | | // 设置曝光时间 |
| | | result = _camera.IMV_SetDoubleFeatureValue("ExposureTime", value); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"设置曝光时间失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"设置曝光时间失败,错误码:{result}"); |
| | | throw new Exception(SN + $"设置曝光时间失败,错误码:{result}"); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置曝光时间失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置曝光时间失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置曝光时间失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | int result = _camera.IMV_GetDoubleFeatureValue("ExposureTime", ref value); |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取曝光时间失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取曝光时间失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取曝光时间失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | string gainFeature = _camera.IMV_FeatureIsValid("Gain") ? "Gain" : "GainRaw"; |
| | |
| | | int result = _camera.IMV_GetDoubleFeatureMin(gainFeature, ref minGain); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"获取增益最小值失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"获取增益最小值失败,错误码:{result}"); |
| | | throw new Exception(SN + $"获取增益最小值失败,错误码:{result}"); |
| | | } |
| | | |
| | | result = _camera.IMV_GetDoubleFeatureMax(gainFeature, ref maxGain); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"获取增益最大值失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"获取增益最大值失败,错误码:{result}"); |
| | | throw new Exception(SN + $"获取增益最大值失败,错误码:{result}"); |
| | | } |
| | | |
| | | if (gain < minGain) gain = minGain; |
| | |
| | | result = _camera.IMV_SetDoubleFeatureValue(gainFeature, gain); |
| | | if (result != IMVDefine.IMV_OK) |
| | | { |
| | | throw new Exception($"设置增益失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"设置增益失败,错误码:{result}"); |
| | | throw new Exception(SN + $"设置增益失败,错误码:{result}"); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置增益失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置增益失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置增益失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (_camera == null || !_camera.IMV_IsOpen()) |
| | | { |
| | | throw new Exception("相机未打开"); |
| | | AsyncLogHelper.Error(SN + "相机未打开"); |
| | | throw new Exception(SN + "相机未打开"); |
| | | } |
| | | |
| | | string gainFeature = _camera.IMV_FeatureIsValid("Gain") ? "Gain" : "GainRaw"; |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取增益失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取增益失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取增益失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置触发极性失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置触发极性失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置触发极性失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取触发极性失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取触发极性失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取触发极性失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置触发滤波失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置触发滤波失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置触发滤波失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取触发滤波失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取触发滤波失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取触发滤波失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置触发延时失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置触发延时失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置触发延时失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取触发延时失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取触发延时失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取触发延时失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置信号线模式失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置信号线模式失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置信号线模式失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"设置信号线状态失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"设置信号线状态失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"设置信号线状态失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"获取信号线状态失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取信号线状态失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"获取信号线状态失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"自动白平衡失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"自动白平衡失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"自动白平衡失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | if ((uint)result != 0x80000001 && result != -119 && result != -102) // 超时错误代码 |
| | | { |
| | | // 非超时错误 |
| | | System.Diagnostics.Debug.WriteLine($"获取图像帧失败,错误码:{result}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"获取图像帧失败,错误码:{result}"); |
| | | AsyncLogHelper.Error(SN + $"获取图像帧失败,错误码:{result}"); |
| | | Thread.Sleep(10); // 出错时稍作等待 |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"采集线程异常:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"采集线程异常:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"采集线程异常:{ex.Message}"); |
| | | Thread.Sleep(10); |
| | | } |
| | | |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"处理图像帧失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"处理图像帧失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"处理图像帧失败:{ex.Message}"); |
| | | } |
| | | finally |
| | | { |
| | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"图像格式转换失败:{ex.Message}"); |
| | | System.Diagnostics.Debug.WriteLine(SN + $"图像格式转换失败:{ex.Message}"); |
| | | AsyncLogHelper.Error(SN + $"图像格式转换失败:{ex.Message}"); |
| | | return null; |
| | | } |
| | | } |
| | |
| | | using LB_SmartVisionCameraDevice.PHM6000; |
| | | using LB_SmartVisionCameraSDK.PHM6000; |
| | | using LB_SmartVisionCommon; |
| | | using LB_VisionProcesses.Cameras; |
| | | using Sunny.UI.Win32; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Drawing; |
| | |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | using LB_SmartVisionCameraSDK.PHM6000; |
| | | using LB_VisionProcesses.Cameras; |
| | | using LB_SmartVisionCommon; |
| | | using LB_SmartVisionCameraDevice.PHM6000; |
| | | |
| | | namespace LB_VisionProcesses.Cameras.LBCameras |
| | | { |
| | |
| | | { |
| | | AsyncLogHelper.Info($"LBCamera[{SN}]: Flushing partial buffer ({_currentLineCount} lines) on completion"); |
| | | CreateAndFireBitmap(); |
| | | |
| | | _currentLineCount = 0; |
| | | } |
| | | } |
| | |
| | | AsyncLogHelper.Info($"LBCamera[{SN}]: Frame {_frameCount} generated ({width}x{height})"); |
| | | |
| | | // 异步触发事件,避免阻塞SDK回调线程 |
| | | Task.Run(() => |
| | | Task.Factory.StartNew(() => |
| | | { |
| | | try |
| | | { |
| | | ImageGrabbed?.Invoke(this, new LBCameraEventArgs(SN, bmp, true)); |
| | | CallBackImg = (Bitmap)bmp.Clone(); |
| | | if (CallBackImg == null) |
| | | { |
| | | return; |
| | | } |
| | | if (GetTriggerMode(out TriggerMode mode, out TriggerSource source)) |
| | | { |
| | | if (mode == TriggerMode.On && source != TriggerSource.Software) |
| | | TriggerRunMessageReceived?.Invoke(SN, source.ToString()); // 触发运行事件 |
| | | } |
| | | bmp.Dispose(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | |
| | | btnConnect = new Button(); |
| | | cmbIP = new ComboBox(); |
| | | lblIP = new Label(); |
| | | lblDataType = new Label(); |
| | | cmbDataType = new ComboBox(); |
| | | grpReceive = new GroupBox(); |
| | | txtReceiveMsg = new TextBox(); |
| | | txtSendMsg = new TextBox(); |
| | |
| | | grpSetting.ForeColor = SystemColors.Control; |
| | | grpSetting.Location = new Point(18, 74); |
| | | grpSetting.Name = "grpSetting"; |
| | | grpSetting.Size = new Size(200, 146); |
| | | grpSetting.Size = new Size(200, 210); |
| | | grpSetting.TabIndex = 0; |
| | | grpSetting.TabStop = false; |
| | | grpSetting.Text = "通讯配置"; |
| | |
| | | grpTest.Controls.Add(lblAddress); |
| | | grpTest.Controls.Add(lblMsg); |
| | | grpTest.Controls.Add(txtMsg); |
| | | grpTest.Controls.Add(lblDataType); |
| | | grpTest.Controls.Add(cmbDataType); |
| | | grpTest.ForeColor = SystemColors.Control; |
| | | grpTest.Location = new Point(241, 74); |
| | | grpTest.Name = "grpTest"; |
| | | grpTest.Size = new Size(320, 146); |
| | | grpTest.Size = new Size(320, 210); |
| | | grpTest.TabIndex = 12; |
| | | grpTest.TabStop = false; |
| | | grpTest.Text = "通讯测试"; |
| | | // |
| | | // lblDataType |
| | | // |
| | | lblDataType.AutoSize = true; |
| | | lblDataType.Location = new Point(160, 115); |
| | | lblDataType.Name = "lblDataType"; |
| | | lblDataType.Size = new Size(32, 17); |
| | | lblDataType.TabIndex = 8; |
| | | lblDataType.Text = "类型"; |
| | | // |
| | | // cmbDataType |
| | | // |
| | | cmbDataType.FormattingEnabled = true; |
| | | cmbDataType.Location = new Point(200, 112); |
| | | cmbDataType.Name = "cmbDataType"; |
| | | cmbDataType.Size = new Size(94, 25); |
| | | cmbDataType.TabIndex = 9; |
| | | // |
| | | // lblCom |
| | | // |
| | |
| | | // btnRun |
| | | // |
| | | btnRun.ForeColor = SystemColors.WindowText; |
| | | btnRun.Location = new Point(215, 109); |
| | | btnRun.Location = new Point(215, 168); |
| | | btnRun.Name = "btnRun"; |
| | | btnRun.Size = new Size(75, 23); |
| | | btnRun.TabIndex = 3; |
| | |
| | | private ReaLTaiizor.Controls.ControlBox controlBox1; |
| | | private TextBox txtAddress; |
| | | private Label lblAddress; |
| | | private Label lblDataType; |
| | | private ComboBox cmbDataType; |
| | | } |
| | | } |
| | |
| | | |
| | | 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) |
| | |
| | | txtIP.Visible = false; |
| | | this.lblAddress.Visible = false; |
| | | this.txtAddress.Visible = false; |
| | | this.lblDataType.Visible = false; |
| | | this.cmbDataType.Visible = false; |
| | | |
| | | |
| | | lblIP.Text = "串口号"; |
| | | lblIP.Text = "波特率"; |
| | | lblIP.Text = "波特率"; // Bug: 这里 lblPort 应该被设置为 "波特率",但原代码复用了 lblIP? 不,lblIP.Text被设了两次。 |
| | | lblPort.Text = "波特率"; // 修正原代码的潜在Bug |
| | | |
| | | cmbIP.Text = communicator.CommunicatorConnections["地址"].ToString(); |
| | | txtPort.Text = communicator.CommunicatorConnections["端口"].ToString(); |
| | |
| | | txtIP.Visible = true; |
| | | this.lblAddress.Visible = false; |
| | | this.txtAddress.Visible = false; |
| | | this.lblDataType.Visible = false; |
| | | this.cmbDataType.Visible = false; |
| | | |
| | | |
| | | lblIP.Text = "监控文件"; |
| | | lblIP.Text = "写入文件"; |
| | | lblPort.Text = "写入文件"; // 修正原代码可能的错误 |
| | | |
| | | txtIP.Text = communicator.CommunicatorConnections["地址"].ToString(); |
| | | txtPort.Text = communicator.CommunicatorConnections["端口"].ToString(); |
| | |
| | | txtIP.Visible = true; |
| | | this.lblAddress.Visible = true; |
| | | this.txtAddress.Visible = true; |
| | | this.lblDataType.Visible = true; |
| | | this.cmbDataType.Visible = true; |
| | | |
| | | lblIP.Text = "IP"; |
| | | lblIP.Text = "槽"; |
| | | 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; |
| | | } |
| | |
| | | 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"; |
| | | lblIP.Text = "端口"; |
| | | lblPort.Text = "端口"; |
| | | |
| | | txtIP.Text = communicator.CommunicatorConnections["地址"].ToString(); |
| | | txtPort.Text = communicator.CommunicatorConnections["端口"].ToString(); |
| | |
| | | { |
| | | 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 |
| | | { |
| | |
| | | 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; |
| | | |
| | | communicator.SendMessage(txtSendMsg.Text); |
| | | |
| | | ShowSendMsg(txtSendMsg.Text); |
| | | if (communicator.SendMessage(txtSendMsg.Text)) |
| | | { |
| | | ShowSendMsg(txtSendMsg.Text); |
| | | } |
| | | else |
| | | { |
| | | ShowLogMsg(communicator.Msg); |
| | | } |
| | | } |
| | | |
| | | private void btnRuleSend_Click(object sender, EventArgs e) |
| | |
| | | //HexByte = strToHexByte(strSendMsg + crcString); |
| | | SendMsg = SendMsg + crcString; |
| | | |
| | | communicator.SendMessage(SendMsg); |
| | | if (communicator.SendMessage(SendMsg)) |
| | | { |
| | | ShowSendMsg(SendMsg); |
| | | } |
| | | else |
| | | { |
| | | ShowLogMsg(communicator.Msg); |
| | | } |
| | | } |
| | | |
| | | private void btnRun_Click(object sender, EventArgs e) |
| | |
| | | using LB_SmartVisionCommon; |
| | | using LB_SmartVisionCommon; |
| | | using S7.Net; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using System.Text.RegularExpressions; |
| | | using System.Threading; |
| | | |
| | | namespace LB_VisionProcesses.Communicators.SiemensS7 |
| | | { |
| | | public class SiemensLBS7 : BaseCommunicator |
| | | { |
| | | private Plc plc; |
| | | public string variable = string.Empty; |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="name"></param> |
| | | public SiemensLBS7(string name = "西门子S7") |
| | | // 默认变量地址 |
| | | public string variable = "DB1.DBD0"; |
| | | // 数据类型 |
| | | private string dataType = "String"; |
| | | |
| | | // 缓存连接参数 |
| | | private string ip = "127.0.0.1"; |
| | | private short rack = 0; |
| | | private short slot = 1; |
| | | private CpuType cpuType = CpuType.S71500; |
| | | |
| | | public SiemensLBS7(string name = "西门子S7") : base(name) |
| | | { |
| | | CommunicatorConnections.Add("地址", "127.0.0.1"); |
| | | CommunicatorConnections.Add("端口", "1"); |
| | | CommunicatorConnections.Add("型号", S7.Net.CpuType.S71500); |
| | | CommunicatorBrand = CommunicatorBrand.SiemensS7; |
| | | CommunicatorName = name; |
| | | CommunicatorBrand = CommunicatorBrand.SiemensS7; |
| | | |
| | | // 初始化默认参数 |
| | | if (!CommunicatorConnections.Contains("地址")) CommunicatorConnections.Add("地址", "192.168.0.1"); |
| | | if (!CommunicatorConnections.Contains("机架号")) CommunicatorConnections.Add("机架号", "0"); |
| | | if (!CommunicatorConnections.Contains("插槽号")) CommunicatorConnections.Add("插槽号", "1"); |
| | | if (!CommunicatorConnections.Contains("型号")) CommunicatorConnections.Add("型号", CpuType.S71500); |
| | | if (!CommunicatorConnections.Contains("变量地址")) CommunicatorConnections.Add("变量地址", "DB1.DBD0"); |
| | | if (!CommunicatorConnections.Contains("数据类型")) CommunicatorConnections.Add("数据类型", "String"); |
| | | |
| | | // 兼容旧配置 "端口" |
| | | if (CommunicatorConnections.Contains("端口")) |
| | | { |
| | | CommunicatorConnections["插槽号"] = CommunicatorConnections["端口"]; |
| | | } |
| | | |
| | | // 设置默认心跳消息 |
| | | strHeartbeat = "HEARTBEAT"; |
| | | } |
| | | |
| | | public override bool Connect() |
| | | { |
| | | try |
| | | { |
| | | string IP = CommunicatorConnections["地址"].ToString(); |
| | | short slot; |
| | | short.TryParse(CommunicatorConnections["端口"].ToString(), out slot); |
| | | S7.Net.CpuType cpuType = (CpuType)CommunicatorConnections["型号"]; |
| | | variable = CommunicatorConnections["变量地址"].ToString(); |
| | | plc = new Plc(cpuType, IP, 0, slot); |
| | | plc.Open(); |
| | | return true; |
| | | // 更新参数 |
| | | if (CommunicatorConnections.Contains("地址")) ip = CommunicatorConnections["地址"].ToString(); |
| | | |
| | | if (CommunicatorConnections.Contains("机架号")) |
| | | short.TryParse(CommunicatorConnections["机架号"].ToString(), out rack); |
| | | |
| | | if (CommunicatorConnections.Contains("插槽号")) |
| | | short.TryParse(CommunicatorConnections["插槽号"].ToString(), out slot); |
| | | else if (CommunicatorConnections.Contains("端口")) |
| | | short.TryParse(CommunicatorConnections["端口"].ToString(), out slot); |
| | | |
| | | if (CommunicatorConnections.Contains("型号")) |
| | | { |
| | | if (CommunicatorConnections["型号"] is CpuType type) |
| | | cpuType = type; |
| | | else |
| | | Enum.TryParse(CommunicatorConnections["型号"].ToString(), out cpuType); |
| | | } |
| | | |
| | | if (CommunicatorConnections.Contains("变量地址")) |
| | | variable = CommunicatorConnections["变量地址"].ToString(); |
| | | |
| | | if (CommunicatorConnections.Contains("数据类型")) |
| | | dataType = CommunicatorConnections["数据类型"].ToString(); |
| | | |
| | | // 关闭旧连接 |
| | | plc?.Close(); |
| | | |
| | | plc = new Plc(cpuType, ip, rack, slot); |
| | | plc.Open(); |
| | | |
| | | if (plc.IsConnected) |
| | | { |
| | | bConnected = true; |
| | | AsyncLogHelper.Info($"Device:[{CommunicatorName}] 已连接到 {ip} 机架:{rack} 插槽:{slot}"); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | bConnected = false; |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] 连接失败: IsConnected 为 false"); |
| | | return false; |
| | | } |
| | | } |
| | | catch |
| | | catch (Exception ex) |
| | | { |
| | | bConnected = false; |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] 连接错误: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | { |
| | | try |
| | | { |
| | | plc?.Close(); |
| | | if (plc != null) |
| | | { |
| | | plc.Close(); |
| | | bConnected = false; |
| | | AsyncLogHelper.Info($"Device:[{CommunicatorName}] 已断开连接"); |
| | | } |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] 断开连接错误: {ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | public override bool SendMessage(string message) |
| | | { |
| | | if (plc == null || !plc.IsConnected) |
| | | { |
| | | Msg = "连接未开启"; |
| | | return false; |
| | | } |
| | | |
| | | if (message == strHeartbeat) return plc.IsConnected; |
| | | |
| | | try |
| | | { |
| | | string targetVar = variable; |
| | | string strValue = message; |
| | | |
| | | // 简单的协议解析:地址:值 |
| | | if (message.Contains(":")) |
| | | { |
| | | var parts = message.Split(new char[] { ':' }, 2); |
| | | if (parts.Length == 2 && !string.IsNullOrWhiteSpace(parts[0])) |
| | | { |
| | | targetVar = parts[0]; |
| | | strValue = parts[1]; |
| | | } |
| | | } |
| | | |
| | | object valueToWrite = strValue; |
| | | // 获取当前数据类型配置 |
| | | string currentDataType = CommunicatorConnections.Contains("数据类型") ? CommunicatorConnections["数据类型"].ToString() : "String"; |
| | | |
| | | // 根据配置的数据类型进行转换 |
| | | try |
| | | { |
| | | switch (currentDataType) |
| | | { |
| | | case "Bool": |
| | | if (strValue == "1") valueToWrite = true; |
| | | else if (strValue == "0") valueToWrite = false; |
| | | else valueToWrite = bool.Parse(strValue); |
| | | break; |
| | | case "Byte": |
| | | valueToWrite = byte.Parse(strValue); |
| | | break; |
| | | case "Int": // 16-bit |
| | | valueToWrite = short.Parse(strValue); |
| | | break; |
| | | case "DInt": // 32-bit |
| | | valueToWrite = int.Parse(strValue); |
| | | break; |
| | | case "Word": // 16-bit unsigned |
| | | valueToWrite = ushort.Parse(strValue); |
| | | break; |
| | | case "DWord": // 32-bit unsigned |
| | | valueToWrite = uint.Parse(strValue); |
| | | break; |
| | | case "Real": // Float |
| | | valueToWrite = float.Parse(strValue); |
| | | break; |
| | | case "Double": // LReal |
| | | valueToWrite = double.Parse(strValue); |
| | | break; |
| | | case "String": |
| | | default: |
| | | valueToWrite = strValue; |
| | | break; |
| | | } |
| | | } |
| | | catch (FormatException) |
| | | { |
| | | Msg = $"无效的{currentDataType}值,请输入正确格式。"; |
| | | if (currentDataType == "Bool") Msg += " (true/false 或 1/0)"; |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] {Msg}"); |
| | | return false; |
| | | } |
| | | catch (Exception castEx) |
| | | { |
| | | Msg = $"数据转换错误({currentDataType}): {castEx.Message}"; |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] {Msg}"); |
| | | return false; |
| | | } |
| | | |
| | | // 尝试写入 |
| | | plc.Write(targetVar, valueToWrite); |
| | | AsyncLogHelper.Info($"Device:[{CommunicatorName}] 写入({currentDataType}) {targetVar} = {valueToWrite}"); |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Msg = $"发送消息错误: {ex.Message}"; |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] {Msg}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | public override string ReceiveMsg() |
| | | { |
| | | if (plc == null || !plc.IsConnected) return string.Empty; |
| | | |
| | | try |
| | | { |
| | | // 获取当前数据类型配置 |
| | | string currentDataType = CommunicatorConnections.Contains("数据类型") ? CommunicatorConnections["数据类型"].ToString() : "String"; |
| | | |
| | | if (currentDataType == "String") |
| | | { |
| | | var match = Regex.Match(variable, @"DB(\d+)\.DB[B|W|D|X]?(\d+)", RegexOptions.IgnoreCase); |
| | | if (match.Success) |
| | | { |
| | | try |
| | | { |
| | | int db = int.Parse(match.Groups[1].Value); |
| | | int startByte = int.Parse(match.Groups[2].Value); |
| | | |
| | | // 读取头部 (MaxLen, ActLen) |
| | | byte[] header = plc.ReadBytes(DataType.DataBlock, db, startByte, 2); |
| | | if (header != null && header.Length >= 2) |
| | | { |
| | | int actLen = header[1]; |
| | | if (actLen > 0) |
| | | { |
| | | // 读取实际字符数据 |
| | | byte[] strBytes = plc.ReadBytes(DataType.DataBlock, db, startByte + 2, actLen); |
| | | strReceiveMsg = Encoding.ASCII.GetString(strBytes); |
| | | return strReceiveMsg; |
| | | } |
| | | else |
| | | { |
| | | strReceiveMsg = string.Empty; |
| | | return strReceiveMsg; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] 读取S7String失败: {ex.Message}"); |
| | | } |
| | | } |
| | | // 如果正则不匹配或读取失败,回退到默认读取 |
| | | } |
| | | |
| | | var result = plc.Read(variable); |
| | | if (result != null) |
| | | { |
| | | // 尝试根据 dataType 格式化输出 (S7.Net 读出来的类型可能与预期不符,特别是 DWord/Real) |
| | | // 例如 DBD0 默认读出来是 UInt32,如果 dataType 是 Real,需要转换 |
| | | if (currentDataType == "Real" && (result is uint || result is int)) |
| | | { |
| | | byte[] bytes = BitConverter.GetBytes(Convert.ToUInt32(result)); |
| | | float f = BitConverter.ToSingle(bytes, 0); |
| | | strReceiveMsg = f.ToString(); |
| | | } |
| | | else |
| | | { |
| | | strReceiveMsg = result.ToString(); |
| | | } |
| | | return strReceiveMsg; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}] 接收消息错误: {ex.Message}"); |
| | | } |
| | | return string.Empty; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 带填充的 S7 字符串写入,防止残留数据 |
| | | /// </summary> |
| | | private bool WriteS7StringWithPadding(string address, string value) |
| | | { |
| | | try |
| | | { |
| | | // 解析地址,例如 DB1.DBB0, DB1.DBD0 |
| | | var match = Regex.Match(address, @"DB(\d+)\.DB[B|W|D|X]?(\d+)", RegexOptions.IgnoreCase); |
| | | if (!match.Success) return false; |
| | | |
| | | int db = int.Parse(match.Groups[1].Value); |
| | | int startByte = int.Parse(match.Groups[2].Value); |
| | | |
| | | byte maxLen = 254; // 默认最大值 |
| | | try |
| | | { |
| | | var header = plc.ReadBytes(DataType.DataBlock, db, startByte, 1); |
| | | if (header != null && header.Length > 0 && header[0] > 0) |
| | | { |
| | | maxLen = header[0]; |
| | | } |
| | | } |
| | | catch { } |
| | | |
| | | byte[] buffer = new byte[maxLen + 2]; |
| | | buffer[0] = maxLen; |
| | | int currentLen = Math.Min(value.Length, maxLen); |
| | | buffer[1] = (byte)currentLen; |
| | | |
| | | if (currentLen > 0) |
| | | { |
| | | byte[] strBytes = Encoding.ASCII.GetBytes(value); |
| | | Array.Copy(strBytes, 0, buffer, 2, Math.Min(strBytes.Length, currentLen)); |
| | | } |
| | | |
| | | plc.WriteBytes(DataType.DataBlock, db, startByte, buffer); |
| | | return true; |
| | | } |
| | | catch |
| | |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | public override bool SendMessage(string message) |
| | | |
| | | public object Read(string address) |
| | | { |
| | | try |
| | | { |
| | | if (plc!=null) |
| | | { |
| | | if (string.IsNullOrEmpty(variable)) |
| | | { |
| | | variable = CommunicatorConnections["变量地址"].ToString(); |
| | | } |
| | | plc.Write(variable, message); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | return false; |
| | | } |
| | | if (plc == null || !plc.IsConnected) return null; |
| | | return plc.Read(address); |
| | | } |
| | | |
| | | public void Write(string address, object value) |
| | | { |
| | | if (plc != null && plc.IsConnected) |
| | | plc.Write(address, value); |
| | | } |
| | | |
| | | public override void Dispose() |
| | | { |
| | | try |
| | | { |
| | | AsyncLogHelper.Info($"Device:[{CommunicatorName}],Dispose()"); |
| | | |
| | | AsyncLogHelper.Info($"Device:[{CommunicatorName}],释放资源(Dispose)"); |
| | | plc?.Close(); |
| | | plc = null; |
| | | |
| | | // Suppress finalization. |
| | | GC.SuppressFinalize(this); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}],Dispose(),Error" + ex); |
| | | AsyncLogHelper.Error($"Device:[{CommunicatorName}],释放资源(Dispose)错误: " + ex.Message); |
| | | } |
| | | } |
| | | } |