From d0c990eaf6cfdbf77c1f4f8db272f4964ec43310 Mon Sep 17 00:00:00 2001
From: C3204 <zhengyabo@lanpucloud.cn>
Date: 星期四, 15 一月 2026 15:58:15 +0800
Subject: [PATCH] 优化西门子S7通讯:支持多数据类型、UI布局调整及配置持久化修复   详细说明:    1. 通讯核心 (SiemensLBS7)        * 多类型支持:完善 SendMessage 和 ReceiveMsg,支持 Bool, Byte, Int, DInt, Real, Double, Word, DWord, String的读写。        * Bool 解析优化:增强布尔值解析逻辑,支持字符串 "1"/"0" 及 "True"/"False"(不区分大小写)。        * 错误反馈:捕获数据转换异常(如格式错误),将具体错误信息写入 Msg 属性,便于 UI 展示。

---
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs     |   28 ++
 LB_SmartVision/ProcessRun/ProcessRunBll.cs                               |    7 
 LB_SmartVision/VisionForm.cs                                             |   16 
 LB_VisionFlowNode/FlowPanel.cs                                           |    2 
 LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs            |   29 ++
 LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs                |  358 +++++++++++++++++++++++---
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs |  151 +++++++---
 LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs          |   58 ++++
 LB_VisionProcesses/Communicators/CommunicatorForm.cs                     |   84 +++++
 9 files changed, 601 insertions(+), 132 deletions(-)

diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs
index e008eb3..5edd886 100644
--- a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.Designer.cs
@@ -44,6 +44,8 @@
             lblType = new Label();
             lblAddress = new Label();
             lblIP = new Label();
+            cmbDataType = new ComboBox();
+            lblDataType = new Label();
             tableLayoutPanel2 = new TableLayoutPanel();
             btnRuleSend = new Button();
             btnSend = new Button();
@@ -63,9 +65,10 @@
             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;
@@ -81,14 +84,15 @@
             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
@@ -96,9 +100,11 @@
             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 = "閫氳璁板綍";
@@ -106,20 +112,22 @@
             // 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
@@ -134,21 +142,26 @@
             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;
             // 
@@ -156,92 +169,123 @@
             // 
             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;
@@ -251,9 +295,10 @@
             // 
             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;
@@ -268,11 +313,12 @@
             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;
@@ -288,7 +334,8 @@
             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";
@@ -300,19 +347,21 @@
             // 
             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;
@@ -351,5 +400,7 @@
         private ComboBox cmbType;
         private Label lblAddress;
         private TextBox txtAddress;
+        private Label lblDataType;
+        private ComboBox cmbDataType;
     }
 }
\ No newline at end of file
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs
index 0e70eb0..c748948 100644
--- a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorForm.cs
@@ -44,12 +44,15 @@
             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;
@@ -74,6 +77,8 @@
                 lblAddress.Visible = false;
                 cmbType.Visible = false;
                 txtAddress.Visible = false;
+                lblDataType.Visible = false;
+                cmbDataType.Visible = false;
 
                 lblIP.Text = "COM鍙�";
                 lblPort.Text = "娉㈢壒鐜�";
@@ -81,7 +86,7 @@
             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;
 
@@ -92,6 +97,8 @@
                 lblAddress.Visible = false;
                 cmbType.Visible = false;
                 txtAddress.Visible = false;
+                lblDataType.Visible = false;
+                cmbDataType.Visible = false;
 
                 lblIP.Text = "鍦板潃";
                 lblPort.Text = "绔彛";
@@ -111,6 +118,15 @@
                 {
                     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;
@@ -119,6 +135,9 @@
                 lblAddress.Visible = true;
                 cmbType.Visible = true;
                 txtAddress.Visible = true;
+                lblDataType.Visible = true;
+                cmbDataType.Visible = true;
+                cmbDataType.Enabled = true; // 鍚敤鏁版嵁绫诲瀷閫夋嫨
 
                 lblIP.Text = "IP";
                 lblPort.Text = "妲�";
@@ -127,6 +146,15 @@
             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();
@@ -228,6 +256,24 @@
             }
         }
 
+        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)
@@ -235,6 +281,8 @@
 
             if (communicator.SendMessage(txtSendMsg.Text))
                 ShowSendMsg(txtSendMsg.Text);
+            else
+                ShowLogMsg(communicator.Msg);
         }
 
         private void btnRuleSend_Click(object sender, EventArgs e)
@@ -253,17 +301,15 @@
 
             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);
             }
         }
diff --git a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs
index 0a561a3..ad09050 100644
--- a/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs
+++ b/LB_SmartVision/Forms/Pages/CommunicatorPage/CommunicatorsEditPage.cs
@@ -34,7 +34,9 @@
                 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();
@@ -69,7 +71,9 @@
                 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;
@@ -135,7 +139,27 @@
 
         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;
+                }
+            }
         }
 
         // 绉婚櫎閫氳鍙�
diff --git a/LB_SmartVision/ProcessRun/ProcessRunBll.cs b/LB_SmartVision/ProcessRun/ProcessRunBll.cs
index d2ba837..e91c741 100644
--- a/LB_SmartVision/ProcessRun/ProcessRunBll.cs
+++ b/LB_SmartVision/ProcessRun/ProcessRunBll.cs
@@ -603,9 +603,6 @@
                     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)
@@ -642,7 +639,6 @@
                     {
                         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, ""));
@@ -652,9 +648,8 @@
                     {
                         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);
diff --git a/LB_SmartVision/VisionForm.cs b/LB_SmartVision/VisionForm.cs
index a8fdfcf..f4ed8c8 100644
--- a/LB_SmartVision/VisionForm.cs
+++ b/LB_SmartVision/VisionForm.cs
@@ -841,12 +841,8 @@
                     if (!string.IsNullOrEmpty(CommunicatorAddress) && CommunicatorAddress.Contains("SiemensLBS7"))
                     {
                         // 瀹氫箟姝e垯琛ㄨ揪寮忎互鎻愬彇鍗忚銆両P 鍦板潃鍜岀鍙�
-                        //1.    \((.*?)\)锛歕(鍜� \) 鏄敤浜庡尮閰嶆嫭鍙风殑杞箟瀛楃銆�
-                        //      (.*?) 鏄竴涓潪璐┆鐨勫尮閰嶏紝鐢ㄦ潵鍖归厤绫诲悕锛圡yProcesses.Communicators.TCPServer 鎴� MyProcesses.Communicators.UARTPort锛夈��
-                        //2.    ([^:] +)锛氬尮閰嶅啋鍙蜂箣鍓嶇殑閮ㄥ垎锛屽嵆鍦板潃锛�127.0.0.1 鎴� COM5锛夈�傝繖閲屼娇鐢ㄤ簡[^:] 鏉ュ尮閰嶉櫎浜嗗啋鍙蜂箣澶栫殑浠绘剰瀛楃銆�
-                        //3.    (\d +) 锛氬尮閰嶇鍙e彿锛岀‘淇濆畠鍖归厤涓�涓垨澶氫釜鏁板瓧銆�
-
-                        string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\]$";
+                        // 鏇存柊姝e垯浠ユ敮鎸佸彲閫夌殑鏁版嵁绫诲瀷瀛楁
+                        string pattern = @"^\((?<ClassName>[^)]+)\)\[(?<IP>[^]]+)\]\[(?<Slot>[^]]+)\]\[(?<CpuType>[^]]+)\]\[(?<PlcAddress>[^]]+)\](?:\[(?<DataType>[^]]+)\])?$";
                         Match match = Regex.Match(CommunicatorAddress, pattern);
 
                         if (match.Success)
@@ -856,6 +852,8 @@
                             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;
 
@@ -878,6 +876,7 @@
                             Communicator.CommunicatorConnections.Add("绔彛", Slot);
                             Communicator.CommunicatorConnections.Add("鍨嬪彿", CpuType);
                             Communicator.CommunicatorConnections.Add("鍙橀噺鍦板潃", PlcAddress);
+                            Communicator.CommunicatorConnections.Add("鏁版嵁绫诲瀷", DataType);
                             Communicator.CommunicatorName = CommunicatorName;
                             if (!Communicator.Connect())
                             {
@@ -1038,11 +1037,14 @@
                     {
                         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
diff --git a/LB_VisionFlowNode/FlowPanel.cs b/LB_VisionFlowNode/FlowPanel.cs
index 6f295fd..fd08c76 100644
--- a/LB_VisionFlowNode/FlowPanel.cs
+++ b/LB_VisionFlowNode/FlowPanel.cs
@@ -140,7 +140,7 @@
                     await ExecuteNodeAsync(currentNode, ExecutionContext);
 
                     // 闃叉姝诲惊鐜紝杩愯鏃堕棿瓒呰繃60绉掑垯寮哄埗缁堟
-                    if ((DateTime.Now - StartTime).TotalSeconds > 1000000000)
+                    if ((DateTime.Now - StartTime).TotalSeconds > 10)
                     {
                         _cancellationTokenSource.Cancel();
                         NodesMsg = $"鎵ц鎵�鏈夎妭鐐硅秴杩�10s";
diff --git a/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs b/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs
index d9998c9..6c2c74c 100644
--- a/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs
+++ b/LB_VisionProcesses/Communicators/CommunicatorForm.Designer.cs
@@ -37,6 +37,8 @@
             btnConnect = new Button();
             cmbIP = new ComboBox();
             lblIP = new Label();
+            lblDataType = new Label();
+            cmbDataType = new ComboBox();
             grpReceive = new GroupBox();
             txtReceiveMsg = new TextBox();
             txtSendMsg = new TextBox();
@@ -74,7 +76,7 @@
             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 = "閫氳閰嶇疆";
@@ -196,13 +198,32 @@
             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
             // 
@@ -252,7 +273,7 @@
             // 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;
@@ -412,5 +433,7 @@
         private ReaLTaiizor.Controls.ControlBox controlBox1;
         private TextBox txtAddress;
         private Label lblAddress;
+        private Label lblDataType;
+        private ComboBox cmbDataType;
     }
 }
\ No newline at end of file
diff --git a/LB_VisionProcesses/Communicators/CommunicatorForm.cs b/LB_VisionProcesses/Communicators/CommunicatorForm.cs
index 0de5c45..37d6ac5 100644
--- a/LB_VisionProcesses/Communicators/CommunicatorForm.cs
+++ b/LB_VisionProcesses/Communicators/CommunicatorForm.cs
@@ -56,11 +56,26 @@
 
         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浼氳Е鍙慥alueChanged浜嬩欢锛屾病鏈夎緭鍏ラ�氳鍙g殑鎯呭喌涓嬮�夋嫨鍒�-1
             if (comConfig != null)
@@ -118,10 +133,13 @@
                 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();
@@ -136,10 +154,12 @@
                 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();
@@ -153,12 +173,21 @@
                 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;
             }
@@ -168,12 +197,14 @@
                 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();
@@ -198,6 +229,13 @@
             {
                 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
             {
@@ -263,14 +301,37 @@
             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)
@@ -287,7 +348,14 @@
             //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)
diff --git a/LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs b/LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs
index 006d3c6..84e8566 100644
--- a/LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs
+++ b/LB_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs
@@ -1,45 +1,103 @@
-锘縰sing 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 = "瑗块棬瀛怱7")
+        // 榛樿鍙橀噺鍦板潃
+        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 = "瑗块棬瀛怱7") : 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;
             }
         }
@@ -48,7 +106,223 @@
         {
             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;
+
+                // 绠�鍗曠殑鍗忚瑙f瀽锛氬湴鍧�:鍊�
+                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}");
+                        }
+                    }
+                    // 濡傛灉姝e垯涓嶅尮閰嶆垨璇诲彇澶辫触锛屽洖閫�鍒伴粯璁よ鍙�
+                }
+
+                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
+            {
+                // 瑙f瀽鍦板潃锛屼緥濡� 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
@@ -56,45 +330,31 @@
                 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);
             }
         }
     }

--
Gitblit v1.9.3