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_VisionProcesses/Communicators/SiemensS7/SiemensLBS7.cs |  358 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 309 insertions(+), 49 deletions(-)

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