From 737dec3c384f394fd6f9849b4480b697d1ba35d5 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期二, 17 三月 2026 09:16:44 +0800
Subject: [PATCH] chore: 提交所有当前改动

---
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/MemoryStore.cs |  113 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 97 insertions(+), 16 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/MemoryStore.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/MemoryStore.cs
index 9583b42..295dc8b 100644
--- a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/MemoryStore.cs
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/MemoryStore.cs
@@ -62,7 +62,13 @@
             _config = config ?? throw new ArgumentNullException(nameof(config));
 
             _mRegion = new MRegion(config.MRegionSize);
-            _dbRegion = new DBRegion((ushort)config.DBBlockCount, config.DBBlockSize);
+            var configuredDbNumbers = ResolveConfiguredDbNumbers();
+            var initialDbNumber = configuredDbNumbers.FirstOrDefault();
+            _dbRegion = new DBRegion(initialDbNumber == 0 ? (ushort)1 : initialDbNumber, config.DBBlockSize);
+            foreach (var dbNumber in configuredDbNumbers)
+            {
+                _dbRegion.EnsureBlock(dbNumber);
+            }
             _iRegion = new IRegion(config.IRegionSize);
             _qRegion = new QRegion(config.QRegionSize);
             _tRegion = new TRegion(config.TRegionCount);
@@ -125,7 +131,7 @@
             return regionType switch
             {
                 "M" => ReadMRegion<T>(offset),
-                "DB" => ReadDBRegion<T>(dbNumber.Value, offset),
+                "DB" => ReadDBRegion<T>(dbNumber.Value, offset, bitOffset),
                 "I" => ReadIRegion<T>(offset, bitOffset),
                 "Q" => ReadQRegion<T>(offset, bitOffset),
                 "T" => ReadTRegion<T>(offset),
@@ -204,7 +210,7 @@
                     WriteMRegion(offset, value);
                     break;
                 case "DB":
-                    WriteDBRegion(dbNumber.Value, offset, value);
+                    WriteDBRegion(dbNumber.Value, offset, bitOffset, value);
                     break;
                 case "I":
                     WriteIRegion(offset, bitOffset, value);
@@ -280,12 +286,12 @@
 
             return new Dictionary<string, byte[]>
             {
-                ["M"] = _mRegion.Read(0, (ushort)_mRegion.Size),
+                ["M"] = ReadAllFromRegion(_mRegion, _mRegion.Size),
                 ["DB"] = ExportDBRegion(),
-                ["I"] = _iRegion.Read(0, (ushort)_iRegion.Size),
-                ["Q"] = _qRegion.Read(0, (ushort)_qRegion.Size),
-                ["T"] = _tRegion.Read(0, (ushort)_tRegion.Size),
-                ["C"] = _cRegion.Read(0, (ushort)_cRegion.Size)
+                ["I"] = ReadAllFromRegion(_iRegion, _iRegion.Size),
+                ["Q"] = ReadAllFromRegion(_qRegion, _qRegion.Size),
+                ["T"] = ReadAllFromRegion(_tRegion, _tRegion.Size),
+                ["C"] = ReadAllFromRegion(_cRegion, _cRegion.Size)
             };
         }
 
@@ -381,6 +387,13 @@
                             offset = ushort.Parse(offsetPart.Substring(3));
                         else if (offsetPart.StartsWith("DBB"))
                             offset = ushort.Parse(offsetPart.Substring(3));
+                        else if (offsetPart.StartsWith("DBX"))
+                        {
+                            var dbxParts = offsetPart.Substring(3).Split('.');
+                            offset = ushort.Parse(dbxParts[0]);
+                            var bit = dbxParts.Length > 1 ? byte.Parse(dbxParts[1]) : (byte)0;
+                            return ("DB", offset, dbNumber, bit);
+                        }
                         else
                             offset = ushort.Parse(offsetPart);
                     }
@@ -437,11 +450,11 @@
         /// 娉ㄦ剰锛歴tring绫诲瀷涓嶅彈姝ゆ硾鍨嬫柟娉曟敮鎸侊紙鍙梬here T : struct绾︽潫锛�
         /// 璇蜂娇鐢╓riteBytes/ReadBytes鎴栭�氳繃DBRegion鐩存帴璁块棶瀛楃涓�
         /// </summary>
-        private T ReadDBRegion<T>(ushort dbNumber, ushort offset) where T : struct
+        private T ReadDBRegion<T>(ushort dbNumber, ushort offset, byte? bitOffset) where T : struct
         {
             return typeof(T).Name switch
             {
-                "Boolean" => (T)(object)_dbRegion.ReadBool(dbNumber, offset, 0),
+                "Boolean" => (T)(object)_dbRegion.ReadBool(dbNumber, offset, bitOffset ?? 0),
                 "Int16" => (T)(object)_dbRegion.ReadInt(dbNumber, offset),
                 "Int32" => (T)(object)_dbRegion.ReadDInt(dbNumber, offset),
                 "Single" => (T)(object)_dbRegion.ReadReal(dbNumber, offset),
@@ -507,12 +520,12 @@
         /// 娉ㄦ剰锛歴tring绫诲瀷涓嶅彈姝ゆ硾鍨嬫柟娉曟敮鎸侊紙鍙梬here T : struct绾︽潫锛�
         /// 璇蜂娇鐢╓riteBytes/ReadBytes鎴栭�氳繃DBRegion鐩存帴璁块棶瀛楃涓�
         /// </summary>
-        private void WriteDBRegion<T>(ushort dbNumber, ushort offset, T value) where T : struct
+        private void WriteDBRegion<T>(ushort dbNumber, ushort offset, byte? bitOffset, T value) where T : struct
         {
             switch (typeof(T).Name)
             {
                 case "Boolean":
-                    _dbRegion.WriteBool(dbNumber, offset, 0, (bool)(object)value);
+                    _dbRegion.WriteBool(dbNumber, offset, bitOffset ?? 0, (bool)(object)value);
                     break;
                 case "Int16":
                     _dbRegion.WriteInt(dbNumber, offset, (short)(object)value);
@@ -671,11 +684,11 @@
         private byte[] ExportDBRegion()
         {
             var result = new List<byte>();
-            for (ushort i = 1; i <= _config.DBBlockCount; i++)
+            foreach (var dbNumber in ResolveConfiguredDbNumbers())
             {
                 try
                 {
-                    var blockData = _dbRegion.Read(i, 0, (ushort)_config.DBBlockSize);
+                    var blockData = ReadAllFromDbBlock(dbNumber, _config.DBBlockSize);
                     result.AddRange(blockData);
                 }
                 catch (ArgumentException)
@@ -696,19 +709,87 @@
         private void ImportDBRegion(byte[] data)
         {
             int offset = 0;
-            for (ushort i = 1; i <= _config.DBBlockCount && offset < data.Length; i++)
+            foreach (var dbNumber in ResolveConfiguredDbNumbers())
             {
+                if (offset >= data.Length)
+                {
+                    break;
+                }
+
                 var blockSize = Math.Min(_config.DBBlockSize, data.Length - offset);
                 var blockData = new byte[blockSize];
                 Array.Copy(data, offset, blockData, 0, blockSize);
-                _dbRegion.Write(i, 0, blockData);
+                _dbRegion.Write(dbNumber, 0, blockData);
                 offset += blockSize;
             }
         }
 
         /// <summary>
+        /// 鎸夊垎鐗囪鍙栨暣涓尯鍩燂紝閬垮厤闀垮害瓒呰繃 ushort 瀵艰嚧婧㈠嚭銆�
+        /// </summary>
+        private static byte[] ReadAllFromRegion(IMemoryRegion region, int totalSize)
+        {
+            if (totalSize <= 0)
+            {
+                return Array.Empty<byte>();
+            }
+
+            var result = new byte[totalSize];
+            var copied = 0;
+            while (copied < totalSize)
+            {
+                var chunkLength = (ushort)Math.Min(ushort.MaxValue, totalSize - copied);
+                var chunk = region.Read((ushort)copied, chunkLength);
+                Buffer.BlockCopy(chunk, 0, result, copied, chunkLength);
+                copied += chunkLength;
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// 鎸夊垎鐗囪鍙栨暣涓� DB 鍧楋紝閬垮厤 DBBlockSize=65536 鏃� ushort 杞崲涓� 0銆�
+        /// </summary>
+        private byte[] ReadAllFromDbBlock(ushort dbNumber, int blockSize)
+        {
+            if (blockSize <= 0)
+            {
+                return Array.Empty<byte>();
+            }
+
+            var result = new byte[blockSize];
+            var copied = 0;
+            while (copied < blockSize)
+            {
+                var chunkLength = (ushort)Math.Min(ushort.MaxValue, blockSize - copied);
+                var chunk = _dbRegion.Read(dbNumber, (ushort)copied, chunkLength);
+                Buffer.BlockCopy(chunk, 0, result, copied, chunkLength);
+                copied += chunkLength;
+            }
+
+            return result;
+        }
+
+        /// <summary>
         /// 閲婃斁璧勬簮
         /// </summary>
+        private List<ushort> ResolveConfiguredDbNumbers()
+        {
+            if (_config.DBBlockNumbers != null && _config.DBBlockNumbers.Count > 0)
+            {
+                return _config.DBBlockNumbers
+                    .Where(x => x > 0 && x <= ushort.MaxValue)
+                    .Distinct()
+                    .Select(x => (ushort)x)
+                    .ToList();
+            }
+
+            return Enumerable
+                .Range(1, Math.Max(1, _config.DBBlockCount))
+                .Select(x => (ushort)x)
+                .ToList();
+        }
+
         public void Dispose()
         {
             Dispose(true);

--
Gitblit v1.9.3