xu.lu 2 år sedan
förälder
incheckning
f40de2e5a0
100 ändrade filer med 8042 tillägg och 14 borttagningar
  1. 7 14
      ZT_1C.sln
  2. 92 0
      成品库/WCS.WorkEngineering/Extensions/BCRExtension.cs
  3. 431 0
      成品库/WCS.WorkEngineering/Extensions/DeviceExtension.cs
  4. 43 0
      成品库/WCS.WorkEngineering/Extensions/FlagExtension.cs
  5. 12 0
      成品库/WCS.WorkEngineering/Extensions/RGVExtension.cs
  6. 61 0
      成品库/WCS.WorkEngineering/Extensions/SRMExtension.cs
  7. 59 0
      成品库/WCS.WorkEngineering/Extensions/StationExtension.cs
  8. 143 0
      成品库/WCS.WorkEngineering/Extensions/TaskExtension.cs
  9. 12 0
      成品库/WCS.WorkEngineering/Extensions/TrussExtebsion.cs
  10. 95 0
      成品库/WCS.WorkEngineering/Extensions/WorldExtension.cs
  11. 9 0
      成品库/WCS.WorkEngineering/LockHub.cs
  12. 17 0
      成品库/WCS.WorkEngineering/Protocol/BCR/IBCR80.cs
  13. 11 0
      成品库/WCS.WorkEngineering/Protocol/BCR/IBCR81.cs
  14. 51 0
      成品库/WCS.WorkEngineering/Protocol/BCR/IBCR83.cs
  15. 17 0
      成品库/WCS.WorkEngineering/Protocol/BCR/WCS_BCR80.cs
  16. 17 0
      成品库/WCS.WorkEngineering/Protocol/BCR/WCS_BCR81.cs
  17. 17 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/BCRData.cs
  18. 30 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/DeviceData.cs
  19. 44 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/DeviceDataCollection.cs
  20. 60 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/DeviceDataPack.cs
  21. 18 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/ProdLineData.cs
  22. 17 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/RGVData.cs
  23. 14 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/RobotData.cs
  24. 31 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/SRMData.cs
  25. 34 0
      成品库/WCS.WorkEngineering/Protocol/DataStructure/StationData.cs
  26. 11 0
      成品库/WCS.WorkEngineering/Protocol/RGV/IRGV520.cs
  27. 11 0
      成品库/WCS.WorkEngineering/Protocol/RGV/IRGV521.cs
  28. 269 0
      成品库/WCS.WorkEngineering/Protocol/RGV/RGVEnum.cs
  29. 11 0
      成品库/WCS.WorkEngineering/Protocol/SRM/ISRM520.cs
  30. 11 0
      成品库/WCS.WorkEngineering/Protocol/SRM/ISRM521.cs
  31. 11 0
      成品库/WCS.WorkEngineering/Protocol/SRM/ISRM537.cs
  32. 667 0
      成品库/WCS.WorkEngineering/Protocol/SRM/SrmEnum.cs
  33. 83 0
      成品库/WCS.WorkEngineering/Protocol/SRM/WCS_SRM520.cs
  34. 128 0
      成品库/WCS.WorkEngineering/Protocol/SRM/WCS_SRM521.cs
  35. 16 0
      成品库/WCS.WorkEngineering/Protocol/SRM/WCS_SRM537.cs
  36. 11 0
      成品库/WCS.WorkEngineering/Protocol/Station/IStation520.cs
  37. 11 0
      成品库/WCS.WorkEngineering/Protocol/Station/IStation521.cs
  38. 62 0
      成品库/WCS.WorkEngineering/Protocol/Station/IStation523.cs
  39. 8 0
      成品库/WCS.WorkEngineering/Protocol/Station/IStation90.cs
  40. 11 0
      成品库/WCS.WorkEngineering/Protocol/Station/IStation91.cs
  41. 242 0
      成品库/WCS.WorkEngineering/Protocol/Station/StationEnum.cs
  42. 35 0
      成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station520.cs
  43. 39 0
      成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station521.cs
  44. 31 0
      成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station523.cs
  45. 16 0
      成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station90.cs
  46. 27 0
      成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station91.cs
  47. 11 0
      成品库/WCS.WorkEngineering/Protocol/Truss/ITruss520.cs
  48. 11 0
      成品库/WCS.WorkEngineering/Protocol/Truss/ITruss521.cs
  49. 11 0
      成品库/WCS.WorkEngineering/Protocol/Truss/ITruss523.cs
  50. 11 0
      成品库/WCS.WorkEngineering/Protocol/Truss/ITruss530.cs
  51. 11 0
      成品库/WCS.WorkEngineering/Protocol/Truss/ITruss531.cs
  52. 151 0
      成品库/WCS.WorkEngineering/Protocol/Truss/TrussEnum.cs
  53. 76 0
      成品库/WCS.WorkEngineering/ProtocolProxy.cs
  54. 274 0
      成品库/WCS.WorkEngineering/Systems/AgvSystems.cs
  55. 155 0
      成品库/WCS.WorkEngineering/Systems/DataCollectionSysyem.cs
  56. 127 0
      成品库/WCS.WorkEngineering/Systems/DeviceWriteSystem.cs
  57. 65 0
      成品库/WCS.WorkEngineering/Systems/GetDeviceSystem.cs
  58. 111 0
      成品库/WCS.WorkEngineering/Systems/NoInteractionSystems.cs
  59. 44 0
      成品库/WCS.WorkEngineering/Systems/RGVSystems.cs
  60. 60 0
      成品库/WCS.WorkEngineering/Systems/SrmDebugSystem.cs
  61. 370 0
      成品库/WCS.WorkEngineering/Systems/SrmSystems.cs
  62. 118 0
      成品库/WCS.WorkEngineering/Systems/一楼叠盘机入库.cs
  63. 98 0
      成品库/WCS.WorkEngineering/Systems/一楼扫码入库.cs
  64. 120 0
      成品库/WCS.WorkEngineering/Systems/主线分流点.cs
  65. 52 0
      成品库/WCS.WorkEngineering/Systems/桁架.cs
  66. 49 0
      成品库/WCS.WorkEngineering/Systems/桁架分流点.cs
  67. 47 0
      成品库/WCS.WorkEngineering/Systems/桁架缓存放行点.cs
  68. 37 0
      成品库/WCS.WorkEngineering/Systems/湿拉满轮帘线芯股第一次扫码.cs
  69. 58 0
      成品库/WCS.WorkEngineering/Systems/环形库分流点.cs
  70. 28 0
      成品库/WCS.WorkEngineering/WCS.WorkEngineering.csproj
  71. 238 0
      成品库/WCS.WorkEngineering/WebApi/Controllers/AgvApi.cs
  72. 279 0
      成品库/WCS.WorkEngineering/WebApi/Controllers/AgvController.cs
  73. 125 0
      成品库/WCS.WorkEngineering/WebApi/Controllers/IwmsApi.cs
  74. 586 0
      成品库/WCS.WorkEngineering/WebApi/Controllers/WcsController.cs
  75. 423 0
      成品库/WCS.WorkEngineering/WebApi/Controllers/WmsApi.cs
  76. 28 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/AgvResponseCode.cs
  77. 10 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/AddWcsMoveTaskRequest.cs
  78. 118 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/AgvCallbackRequest.cs
  79. 18 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/ApplyEmptySpoolRequest.cs
  80. 50 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/CancelTaskRequest.cs
  81. 68 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/ContinueTaskRequest.cs
  82. 62 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/CopperLineAgvTaskStockInToIWmsRequest.cs
  83. 82 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/CopperLineAgvTaskStockOutToIWmsRequest.cs
  84. 200 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/GenAgvSchedulingTaskRequest.cs
  85. 103 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/zhongTianIntoStockRequest.cs
  86. 79 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/zhongTianOutStockRequest.cs
  87. 29 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/AddWcsMoveTaskResponse.cs
  88. 35 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/ApplyEmptySpoolResponse.cs
  89. 27 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/CancelTaskResponse.cs
  90. 25 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/ContinueTaskResponse.cs
  91. 26 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/GenAgvSchedulingTaskResponse.cs
  92. 22 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/agvCallbackResponse.cs
  93. 28 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/zhongTianIntoStockResponse.cs
  94. 25 0
      成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/zhongTianOutStockResponse.cs
  95. 46 0
      成品库/WCS.WorkEngineering/WebApi/Models/WCS/Request/HandleTaskRequest.cs
  96. 23 0
      成品库/WCS.WorkEngineering/WebApi/Models/WCS/Response/HandleTaskResponse.cs
  97. 32 0
      成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/ApplyStockInLocRequest.cs
  98. 40 0
      成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/ApplyStockOutTaskRequest.cs
  99. 20 0
      成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/CancelTaskVerifyRequest.cs
  100. 47 0
      成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/CompleteTaskRequest.cs

+ 7 - 14
ZT_1C.sln

@@ -11,10 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "分拣库", "分拣库", "{
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "成品库", "成品库", "{576557C6-7A26-48B3-92A4-DCDF4C538B53}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WCS.Entity.Protocol", "成品库\WCS.Entity.Protocol\WCS.Entity.Protocol.csproj", "{417371C6-6347-4BA7-A72A-4380EAFA7012}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WCS.WorkEngineering", "成品库\WCS.WorkEngineering\WCS.WorkEngineering.csproj", "{02DC24F0-2B80-4B20-9B03-8BF619028C15}"
-EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "合金库", "合金库", "{B31D7629-9D55-4C9D-A58F-7F774198A878}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WCS.WorkEngineering", "合金库\WCS.WorkEngineering\WCS.WorkEngineering.csproj", "{AF24EAB4-1592-40A2-B6E1-D3C9EC1ADB42}"
@@ -29,6 +25,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "盘条库", "盘条库", "{
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WCS.WorkEngineering", "盘条库\WCS.WorkEngineering\WCS.WorkEngineering.csproj", "{8F9D2518-A6AA-4F32-94DE-0BCA0DDDA1D9}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WCS.WorkEngineering", "成品库\WCS.WorkEngineering\WCS.WorkEngineering.csproj", "{067B3D90-C0A0-40F5-AA4D-0ABAB61EA536}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -43,14 +41,6 @@ Global
 		{483637A4-0E57-4927-83FE-3AB2195468DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{483637A4-0E57-4927-83FE-3AB2195468DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{483637A4-0E57-4927-83FE-3AB2195468DE}.Release|Any CPU.Build.0 = Release|Any CPU
-		{417371C6-6347-4BA7-A72A-4380EAFA7012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{417371C6-6347-4BA7-A72A-4380EAFA7012}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{417371C6-6347-4BA7-A72A-4380EAFA7012}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{417371C6-6347-4BA7-A72A-4380EAFA7012}.Release|Any CPU.Build.0 = Release|Any CPU
-		{02DC24F0-2B80-4B20-9B03-8BF619028C15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{02DC24F0-2B80-4B20-9B03-8BF619028C15}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{02DC24F0-2B80-4B20-9B03-8BF619028C15}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{02DC24F0-2B80-4B20-9B03-8BF619028C15}.Release|Any CPU.Build.0 = Release|Any CPU
 		{AF24EAB4-1592-40A2-B6E1-D3C9EC1ADB42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{AF24EAB4-1592-40A2-B6E1-D3C9EC1ADB42}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{AF24EAB4-1592-40A2-B6E1-D3C9EC1ADB42}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -67,6 +57,10 @@ Global
 		{8F9D2518-A6AA-4F32-94DE-0BCA0DDDA1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{8F9D2518-A6AA-4F32-94DE-0BCA0DDDA1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{8F9D2518-A6AA-4F32-94DE-0BCA0DDDA1D9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{067B3D90-C0A0-40F5-AA4D-0ABAB61EA536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{067B3D90-C0A0-40F5-AA4D-0ABAB61EA536}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{067B3D90-C0A0-40F5-AA4D-0ABAB61EA536}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{067B3D90-C0A0-40F5-AA4D-0ABAB61EA536}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -74,12 +68,11 @@ Global
 	GlobalSection(NestedProjects) = preSolution
 		{FF8F6281-2169-4EF2-B2F6-A94A0B20867D} = {28F8EE0D-9AD0-46D7-8531-82BA564F23C7}
 		{483637A4-0E57-4927-83FE-3AB2195468DE} = {28F8EE0D-9AD0-46D7-8531-82BA564F23C7}
-		{417371C6-6347-4BA7-A72A-4380EAFA7012} = {576557C6-7A26-48B3-92A4-DCDF4C538B53}
-		{02DC24F0-2B80-4B20-9B03-8BF619028C15} = {576557C6-7A26-48B3-92A4-DCDF4C538B53}
 		{AF24EAB4-1592-40A2-B6E1-D3C9EC1ADB42} = {B31D7629-9D55-4C9D-A58F-7F774198A878}
 		{938C3203-3F97-4E0F-AA9F-5F2BC795698B} = {345EC8E8-4F1D-481D-8A0E-CE066DEE46ED}
 		{A48750DE-D922-498E-B282-FA3D3DFC116D} = {345EC8E8-4F1D-481D-8A0E-CE066DEE46ED}
 		{8F9D2518-A6AA-4F32-94DE-0BCA0DDDA1D9} = {12AEE966-FB30-4F0E-9F65-6E7CB3446DBB}
+		{067B3D90-C0A0-40F5-AA4D-0ABAB61EA536} = {576557C6-7A26-48B3-92A4-DCDF4C538B53}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {C75EF4BD-59B3-4F79-A380-6D452ADFB53E}

+ 92 - 0
成品库/WCS.WorkEngineering/Extensions/BCRExtension.cs

@@ -0,0 +1,92 @@
+using PlcSiemens.Core.Extension;
+using ServiceCenter.Logs;
+using WCS.Core;
+using WCS.WorkEngineering.Protocol.BCR;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    /// <summary>
+    ///  BCR扩展
+    /// </summary>
+    public class BCR : Device<IBCR81>
+    {
+        /// <summary>
+        ///   BCR扩展
+        /// </summary>
+        /// <param name="device"></param>
+        /// <param name="world"></param>
+        public BCR(Device device, World world) : base(device, world)
+        {
+        }
+
+        /// <summary>
+        ///  获取BCR码
+        /// </summary>
+        /// <returns></returns>
+        public string GetBCRCode()
+        {
+            var barcode = Data.Content.Trim('\0');
+
+            if (barcode.IsNullOrWhiteSpace()) throw new KnownException($"{Entity.Code}--扫码失败,内容为空", LogLevelEnum.High);
+
+            return barcode;
+        }
+    }
+
+    /// <summary>
+    ///  BCR83
+    /// </summary>
+    public class BCR83 : Device<IBCR83>
+    {
+        /// <summary>
+        ///   BCR扩展
+        /// </summary>
+        /// <param name="device"></param>
+        /// <param name="world"></param>
+        public BCR83(Device device, World world) : base(device, world)
+        {
+        }
+
+        /// <summary>
+        ///  获取BCR码
+        /// </summary>
+        /// <returns></returns>
+        public string GetBCRCode()
+        {
+            var barcode = Data.BcrCode.Trim('\0');
+
+            if (barcode.IsNullOrWhiteSpace()) throw new KnownException($"{Entity.Code}--扫码失败,内容为空", LogLevelEnum.High);
+
+            return barcode;
+        }
+    }
+
+    /// <summary>
+    ///  BCR扩展
+    /// </summary>
+    public static class BCRExtension
+    {
+        /// <summary>
+        ///  获取BCR码
+        /// </summary>
+        /// <param name="bs"></param>
+        /// <param name="code">BCR对应站点设备号</param>
+        /// <returns></returns>
+        public static string GetBCRCode(this List<BCR> bc, string code)
+        {
+            code = "BCR" + code;
+            var bcr = bc.FirstOrDefault(p => p.Entity.Code == code) ?? throw new KnownException($"未找到扫码器{code}", LogLevelEnum.High);
+            return bcr.GetBCRCode();
+        }
+
+        ///// <summary>
+        /////  获取BCR83码集合
+        ///// </summary>
+        ///// <param name="bc"></param>
+        ///// <returns></returns>
+        //public static string GetBCRCodeList(this BCR83 bc)
+        //{
+
+        //}
+    }
+}

+ 431 - 0
成品库/WCS.WorkEngineering/Extensions/DeviceExtension.cs

@@ -0,0 +1,431 @@
+using PlcSiemens.Core.Extension;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using WCS.Core;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.Station;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    /// <summary>
+    ///  设备扩展
+    /// </summary>
+    public static class DeviceExtension
+    {
+        #region 设备类型
+
+        public static List<ProtocolInfo> ProtocolInfos = new List<ProtocolInfo>();
+
+        /// <summary>
+        ///  是否是巷道
+        /// </summary>
+        /// <param name="source">设备信息</param>
+        /// <returns></returns>
+        public static bool IsTunnel(this Device source)
+        {
+            return source.HasFlag(DeviceFlags.巷道);
+        }
+
+        #endregion 设备类型
+
+        #region 标签判断
+
+        public static bool HasFlag(this Device device, params DeviceFlags[] flag)
+        {
+            foreach (var item in flag)
+            {
+                if (device.HasFlag(item)) continue;
+                return false;
+            }
+            return true;
+        }
+
+        #endregion 标签判断
+
+        #region 协议操作扩展
+
+        public static void AddProtocol<T>(this Device device, int position, ushort db, string ip)
+        {
+            var info = new ProtocolInfo
+            {
+                Position = position,
+                DBInfo = new DBInfo
+                {
+                    No = db,
+                    PLCInfo = new PLCInfo
+                    {
+                        IP = ip,
+                        Port = 102,
+                        Rack = 0,
+                        Slot = 1,
+                        Type = PLCType.Siemens
+                    }
+                }
+            };
+            ProtocolInfos.Add(info);
+            device.AddProtocol<T>(info);
+        }
+
+        #endregion 协议操作扩展
+
+        #region 设备扩展方法
+
+        /// <summary>
+        ///  入库站点是否被禁止
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否被禁止(this Device<IStation520, IStation521, IStation523> device)
+        {
+            var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用");
+            var configs = config.Split(",");
+            if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High);
+        }
+
+        /// <summary>
+        ///  入库站点是否被禁止
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否被禁止(this Device<IStation520, IStation521, IStation523, IBCR81> device)
+        {
+            var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用");
+            var configs = config.Split(",");
+            if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High);
+        }
+
+        /// <summary>
+        ///  入库站点是否被禁止
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否被禁止(this Device<IStation520, IStation521, IStation523, IStation91> device)
+        {
+            var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用");
+            var configs = config.Split(",");
+            if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High);
+        }
+
+        /// <summary>
+        ///  入库站点是否被禁止
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否被禁止(this Device<IStation520, IStation521, IStation523, IStation91, IBCR81> device)
+        {
+            var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用");
+            var configs = config.Split(",");
+            if (configs.Contains(device.Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High);
+        }
+
+        /// <summary>
+        ///  入库站点是否满足执行条件
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否满足执行条件(this Device<IStation520, IStation521, IStation523> device)
+        {
+            if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High);
+            if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
+            if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+        }
+
+        /// <summary>
+        ///  入库站点是否满足执行条件
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否满足执行条件(this Device<IStation520, IStation521, IStation523, IBCR81> device)
+        {
+            if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High);
+            if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
+            if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+        }
+
+        /// <summary>
+        ///  入库站点是否满足执行条件
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否满足执行条件(this Device<IStation520, IStation521, IStation523, IStation91> device)
+        {
+            if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High);
+            if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
+            if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+        }
+
+        /// <summary>
+        ///  入库站点是否满足执行条件
+        /// </summary>
+        /// <returns></returns>
+        public static void 入库站点是否满足执行条件(this Device<IStation520, IStation521, IStation523, IStation91, IBCR81> device)
+        {
+            if (device.Data.VoucherNo != device.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{device.Data.VoucherNo}-DB521:{device.Data2.VoucherNo}", LogLevelEnum.High);
+            if (device.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status) && device.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (device.Data2.Request != 1.ToShort()) throw new KnownException("无请求", LogLevelEnum.Mid);
+            if (!device.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
+            if (device.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+        }
+
+        /// <summary>
+        ///  获取BCR码
+        /// </summary>
+        /// <returns></returns>
+        public static string GetBCRCode(this IBCR81 bCR)
+        {
+            var barcode = bCR.Content.Trim('\0');
+            if (barcode.IsNullOrWhiteSpace()) throw new KnownException($"扫码失败,内容为空", LogLevelEnum.High);
+            return barcode;
+        }
+
+        /// <summary>
+        ///  获取历史扫码记录
+        /// </summary>
+        /// <returns></returns>
+        public static List<string> GetBcrCodeList(this IBCR83 bCR)
+        {
+            return new List<string>() {
+                bCR.BcrCode1.Trim('\0').Trim(),
+                bCR.BcrCode2.Trim('\0').Trim(),
+                bCR.BcrCode3.Trim('\0').Trim(),
+                bCR.BcrCode4.Trim('\0').Trim(),
+                bCR.BcrCode5.Trim('\0').Trim(),
+                bCR.BcrCode6.Trim('\0').Trim(),
+                bCR.BcrCode7.Trim('\0').Trim(),
+                bCR.BcrCode8.Trim('\0').Trim(),
+                bCR.BcrCode9.Trim('\0').Trim(),
+                bCR.BcrCode10.Trim('\0').Trim(),
+                bCR.BcrCode11.Trim('\0').Trim() };
+        }
+
+        #endregion 设备扩展方法
+    }
+
+    /// <summary>
+    ///  设备标签
+    /// </summary>
+    [Flags]
+    public enum DeviceFlags : ulong
+
+    {
+        扫码 = 1L << 0,
+        称重 = 1L << 1,
+        外检 = 1L << 2,
+
+        顶升 = 1L << 3,
+        移栽 = 1L << 4,
+        旋转 = 1L << 5,
+
+        入库 = 1L << 6,
+        出库 = 1L << 7,
+
+        巷道口 = 1L << 8,
+        RGV口 = 1L << 9,
+        AGV口 = 1L << 10,
+
+        直轨 = 1L << 11,
+        弯轨 = 1L << 12,
+        环轨 = 1L << 13,
+
+        巷道 = 1L << 14,
+        堆垛机 = 1L << 15,
+        输送机 = 1L << 16,
+
+        #region 一轨双车堆垛机
+
+        一列堆垛机 = 1L << 23,
+        二列堆垛机 = 1L << 24,
+
+        #endregion 一轨双车堆垛机
+
+        RGV = 1L << 25,
+        桁架 = 1L << 26,
+        一楼扫码 = 1L << 27,
+        满轮主线第一次扫码 = 1L << 28,
+        主线分流点 = 1L << 29,
+        一楼叠盘机 = 1L << 30,
+        环形库分流点 = 1L << 31,
+        桁架分流点 = 1L << 32,
+        桁架缓存放行点 = 1L << 33,
+        桁架取货点 = 1L << 34
+    }
+
+    /// <summary>
+    /// 输送机段信息
+    /// </summary>
+    public class StationSegmentInfo
+    {
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="start">起始设备号</param>
+        /// <param name="end">结束设备号</param>
+        /// <param name="ip">ip</param>
+        public StationSegmentInfo(int start, int end, string ip)
+        {
+            Start = start;
+            End = end;
+            IP = ip;
+        }
+
+        /// <summary>
+        /// 起始设备编号
+        /// </summary>
+        public int Start { get; set; }
+
+        /// <summary>
+        ///结束设备编号
+        /// </summary>
+        public int End { get; set; }
+
+        /// <summary>
+        ///  输送机段所属IP
+        /// </summary>
+        public string IP { get; set; }
+    }
+
+    /// <summary>
+    /// RGV信息
+    /// </summary>
+    public class RGVSegmentInfo
+    {
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="start">起始设备号</param>
+        /// <param name="end">结束设备号</param>
+        /// <param name="ip">ip</param>
+        public RGVSegmentInfo(int code, string ip)
+        {
+            Code = code;
+            IP = ip;
+        }
+
+        /// <summary>
+        /// 设备编号
+        /// </summary>
+        public int Code { get; set; }
+
+        /// <summary>
+        ///  输送机段所属IP
+        /// </summary>
+        public string IP { get; set; }
+    }
+
+    /// <summary>
+    /// 桁架信息
+    /// </summary>
+    public class TrussSegmentInfo
+    {
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="code"></param>
+        /// <param name="ip">ip</param>
+        public TrussSegmentInfo(int code, string ip)
+        {
+            Code = code;
+            IP = ip;
+        }
+
+        /// <summary>
+        /// 设备编号
+        /// </summary>
+        public int Code { get; set; }
+
+        /// <summary>
+        ///  输送机段所属IP
+        /// </summary>
+        public string IP { get; set; }
+    }
+
+    /// <summary>
+    ///  扫码器信息
+    /// </summary>
+    public class BcrInfo
+    {
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="deviceNo">设备编号</param>
+        /// <param name="ip">ip</param>
+        public BcrInfo(int[] deviceNo, string ip)
+        {
+            DeviceNo = deviceNo;
+            IP = ip;
+        }
+
+        /// <summary>
+        ///  设备编号
+        /// </summary>
+        public int[] DeviceNo { get; set; }
+
+        /// <summary>
+        ///  ip
+        /// </summary>
+        public string IP { get; set; }
+    }
+
+    /// <summary>
+    ///  外形信息
+    /// </summary>
+    public class ShapeInfo
+    {
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="deviceNo">设备编号</param>
+        /// <param name="ip">ip</param>
+        public ShapeInfo(int[] deviceNo, string ip)
+        {
+            DeviceNo = deviceNo;
+            IP = ip;
+        }
+
+        /// <summary>
+        ///  设备编号
+        /// </summary>
+        public int[] DeviceNo { get; set; }
+
+        /// <summary>
+        ///  ip
+        /// </summary>
+        public string IP { get; set; }
+    }
+
+    /// <summary>
+    /// 路径信息
+    /// </summary>
+    public class RouteInfo
+    {
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="deviceCode">起始点设备号</param>
+        /// <param name="nextList">下一个设备集合</param>
+        public RouteInfo(string deviceCode, string[] nextList)
+        {
+            DeviceCode = deviceCode;
+            NextList = nextList;
+        }
+
+        /// <summary>
+        ///  设备号
+        /// </summary>
+        public string DeviceCode { get; set; }
+
+        /// <summary>
+        ///  下一个设备
+        /// </summary>
+        public string[] NextList { get; set; }
+    }
+}

+ 43 - 0
成品库/WCS.WorkEngineering/Extensions/FlagExtension.cs

@@ -0,0 +1,43 @@
+using WCS.Core;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    /// <summary>
+    ///  设备标签扩展
+    /// </summary>
+    public static class DeviceFlagExtension
+    {
+        /// <summary>
+        ///  获取指定设备标签的值
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="device"></param>
+        /// <param name="key"></param>
+        /// <returns></returns>
+        public static T GetFlag<T>(this Device device, string key)
+        {
+            if (!device.HasFlag(key))
+            {
+                if (typeof(T) == typeof(int)) device.AddFlag(key, default(int).ToString());
+                else if (typeof(T) == typeof(short)) device.AddFlag(key, default(bool).ToString());
+                else if (typeof(T) == typeof(bool)) device.AddFlag(key, default(bool).ToString());
+            }
+            var valeu = device.GetFlags(key).FirstOrDefault();
+
+            return (T)Convert.ChangeType(valeu, typeof(T));
+        }
+
+        /// <summary>
+        ///  设置指定设备标签的值
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="device"></param>
+        /// <param name="key"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static void SetFlag<T>(this Device device, string key, T value)
+        {
+            device.SetFlag(key, value.ToString());
+        }
+    }
+}

+ 12 - 0
成品库/WCS.WorkEngineering/Extensions/RGVExtension.cs

@@ -0,0 +1,12 @@
+using WCS.Core;
+using WCS.WorkEngineering.Protocol.RGV;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    public class RGV : Device<IRGV520, IRGV521>
+    {
+        public RGV(Device device, World world) : base(device, world)
+        {
+        }
+    }
+}

+ 61 - 0
成品库/WCS.WorkEngineering/Extensions/SRMExtension.cs

@@ -0,0 +1,61 @@
+using ServiceCenter.Extensions;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Protocol.RGV;
+using WCS.WorkEngineering.Protocol.SRM;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    /// <summary>
+    /// 堆垛机扩展
+    /// </summary>
+    public class SRM : Device<ISRM520, ISRM521, ISRM537>
+    {
+        public SRM(Device device, World world) : base(device, world)
+        {
+        }
+
+        /// <summary>
+        ///
+        /// </summary>
+        /// <param name="taskInfo"></param>
+        public void 一轨两车任务下发前置条件判断及处理(WCS_TaskInfo taskInfo)
+        {
+            var col = 0;
+            switch (taskInfo.Type)
+            {
+                case TaskType.SetPlate: return;
+                case TaskType.EnterDepot:
+                    col = taskInfo.AddrTo.Split("-")[1].ToInt();
+                    break;
+
+                case TaskType.OutDepot:
+                    col = taskInfo.AddrFrom.Split("-")[1].ToInt();
+                    break;
+
+                case TaskType.TransferDepot: return;
+                case TaskType.Delivery: return;
+                case TaskType.EmptyInit: return;
+                default: return;
+            }
+            if (Entity.HasFlag(DeviceFlags.一列堆垛机))
+            {
+                if (col > 10)// 跑全程
+                {
+                    if (Data2.Status.HasFlag(SrmStatus.Stopper_Mark))
+                    {
+                    }
+                }
+            }
+            else if (Entity.HasFlag(DeviceFlags.二列堆垛机))
+            {
+                if (col < 11)// 跑全程
+                {
+                    if (Data2.Status.HasFlag(SrmStatus.Stopper_Mark))
+                    {
+                    }
+                }
+            }
+        }
+    }
+}

+ 59 - 0
成品库/WCS.WorkEngineering/Extensions/StationExtension.cs

@@ -0,0 +1,59 @@
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using WCS.Core;
+using WCS.WorkEngineering.Protocol.Station;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    public class Station : Device<IStation520, IStation521, IStation523>
+    {
+        public Station(Device device, World world) : base(device, world)
+        {
+        }
+
+        /// <summary>
+        ///  入库站点是否被禁止
+        /// </summary>
+        /// <returns></returns>
+        public void 入库站点是否被禁止()
+        {
+            var config = RedisHub.Default.Check("ForbidTubuEnter") ?? throw new Exception("请在Redis中配置入库口禁用");
+            var configs = config.Split(",");
+            if (configs.Contains(Entity.Code)) throw new KnownException("当前入库口已被禁用,请联系运维人员了解具体情况", LogLevelEnum.High);
+        }
+
+        /// <summary>
+        ///  入库站点是否满足执行条件
+        /// </summary>
+        /// <returns></returns>
+        public void 入库站点是否满足执行条件()
+        {
+            if (Data.VoucherNo != Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{Data.VoucherNo}-DB521:{Data2.VoucherNo}", LogLevelEnum.High);
+            if (Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (Data3.Status.HasFlag(StationStatus.PH_Status) && Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!Data3.Status.HasFlag(StationStatus.PH_Status) && Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+        }
+
+        /// <summary>
+        ///  主线分流点是否满足执行条件
+        /// </summary>
+        /// <returns></returns>
+        public void 主线分流点是否满足执行条件()
+        {
+            if (Data.VoucherNo != Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{Data.VoucherNo}-DB521:{Data2.VoucherNo}", LogLevelEnum.High);
+            if (Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (Data3.Status.HasFlag(StationStatus.PH_Status) && Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!Data3.Status.HasFlag(StationStatus.PH_Status) && Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+        }
+
+        public string GetBarCode(World world)
+        {
+            var code = "BCR" + Entity.Code;
+            var bcrdev = Device.All.FirstOrDefault(v => v.Code == code) ?? throw new KnownException($"未找到扫码器{code}", LogLevelEnum.High);
+            var bcr = new BCR(bcrdev, world);
+            return bcr.GetBCRCode();
+        }
+    }
+}

+ 143 - 0
成品库/WCS.WorkEngineering/Extensions/TaskExtension.cs

@@ -0,0 +1,143 @@
+using Newtonsoft.Json;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.SqlSugars;
+using WCS.Entity;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    /// <summary>
+    /// 任务扩展
+    /// </summary>
+    public static class TaskExtension
+    {
+        /// <summary>
+        /// 更新任务执行记录
+        /// </summary>
+        /// <param name="task">任务信息</param>
+        /// <param name="db">数据库上下文</param>
+        /// <param name="curPoint">当前地址</param>
+        /// <param name="desc">描述</param>
+        public static void AddWCS_TASK_DTL(this WCS_TaskInfo task, SqlSugarHelper db, string curPoint, string desc) => task.AddWCS_TASK_DTL(db, curPoint, "", desc);
+
+        /// <summary>
+        /// 更新任务执行记录
+        /// </summary>
+        /// <param name="task">任务信息</param>
+        /// <param name="db">数据库上下文</param>
+        /// <param name="curPoint">当前地址</param>
+        /// <param name="NextPoint">下一个地址</param>
+        /// <param name="desc">描述</param>
+        public static void AddWCS_TASK_DTL(this WCS_TaskInfo task, SqlSugarHelper db, string curPoint, string NextPoint, string desc)
+        {
+            db.Default.Insertable(new WCS_TaskDtl
+            {
+                ID = Guid.NewGuid(),
+                ParentTaskCode = task.ID,
+                CurPoint = curPoint,
+                NextPoint = NextPoint,
+                Desc = desc,
+                AddWho = "WCS"
+            }).SplitTable().ExecuteCommand();
+        }
+
+        /// <summary>
+        /// 完成或取消任务
+        /// </summary>
+        /// <param name="taskInfo"></param>
+        /// <param name="db"></param>
+        /// <param name="world"></param>
+        public static void CompleteOrCancelTasks(this WCS_TaskInfo taskInfo, SqlSugarHelper db)
+        {
+            if (taskInfo.Status is not Entity.TaskStatus.Finish and not Entity.TaskStatus.Cancel) throw new KnownException("任务未完成或取消,无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
+            else // 任务完成或取消,进行相关同步动作
+            {
+                WCS_TaskOld taskOld = db.Default.Queryable<WCS_TaskOld>().SplitTable(tabs => tabs.Take(2)).Where(v => v.ID == taskInfo.ID).OrderByDescending(v => v.AddTime).First();
+                if (taskOld is null) throw new KnownException($"WCS_TaskOld表中不存在任务:{taskInfo.ID},无法执行WCS_TaskInfo与WCS_TaskOld同步动作", LogLevelEnum.Mid);
+                else
+                {
+                    //状态
+                    taskOld.Status = taskInfo.Status;
+                    taskOld.Uploaded = taskInfo.Uploaded;
+                    //任务号
+                    taskOld.WmsTask = taskInfo.WmsTask;
+                    taskOld.AgvTaskID = taskInfo.AgvTaskID;
+                    taskOld.TaskGroupKey = taskInfo.TaskGroupKey;
+                    taskOld.Priority = taskInfo.Priority;
+                    //时间与用户
+                    taskOld.AddTime = taskInfo.AddTime;
+                    taskOld.AddWho = taskInfo.AddWho;
+                    taskOld.StartTime = taskInfo.StartTime;
+                    taskOld.EndTime = taskInfo.EedTime;
+                    taskOld.EditWho = taskInfo.EditWho;
+                    taskOld.EditTime = taskInfo.EditTime;
+                    //条码与地址
+                    taskOld.BarCode = taskInfo.BarCode;
+                    taskOld.MaterialCode = taskInfo.MaterialCode;
+                    taskOld.AddrFrom = taskInfo.AddrFrom;
+                    taskOld.AddrTo = taskInfo.AddrTo;
+                    taskOld.LastInteractionPoint = taskInfo.LastInteractionPoint;
+                    taskOld.AddrNext = taskInfo.AddrNext;
+                    taskOld.Tunnel = taskInfo.Tunnel;
+                    taskOld.Floor = taskInfo.Floor;
+                    taskOld.Device = taskInfo.Device;
+                    taskOld.SrmStation = taskInfo.SrmStation;
+                    //码垛信息
+                    taskOld.DocID = taskInfo.DocID;
+                    taskOld.PalletType = taskInfo.PalletType;
+                    taskOld.ProdLine = taskInfo.ProdLine;
+                    taskOld.FullQty = taskInfo.FullQty;
+                    //外形信息
+                    taskOld.Height = taskInfo.Height;
+                    taskOld.Length = taskInfo.Length;
+                    taskOld.Weight = taskInfo.Weight;
+                    //手动处理备注
+                    taskOld.ManualRemarks = taskInfo.ManualRemarks;
+
+                    //更新任务历史表,删除任务当前表
+                    db.Default.Updateable(taskOld).SplitTable().ExecuteCommand();
+                    db.Default.Deleteable(taskInfo).ExecuteCommand();
+                }
+            }
+        }
+
+        ///// <summary>
+        /////  获取出库任务
+        ///// </summary>
+        ///// <param name="taskInfo">任务</param>
+        ///// <param name="db">db</param>
+        ///// <param name="allOutCode">可用出库站台</param>
+        ///// <param name="floor">楼层</param>
+        ///// <param name="obj">堆垛机</param>
+        ///// <param name="index">递归次数</param>
+        ///// <returns></returns>
+        ///// <exception cref="KnownException"></exception>
+        //public static WCS_TaskInfo GetOutTask(this WCS_TaskInfo taskInfo, SqlSugarHelper db, List<string> allOutCode, int floor, SRM obj, int index = 1)
+        //{
+        //    return task;
+        //}
+
+        /// <summary>
+        /// 获取AGV任务ID
+        /// </summary>
+        /// <param name="db">db</param>
+        /// <returns></returns>
+        public static int GetAGVTaskId(this SqlSugarHelper db)
+        {
+            var id = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(v => v.Take(1)).Max(v => v.ID);
+            return id + 1;
+        }
+
+        /// <summary>
+        /// 更新任务执行记录
+        /// </summary>
+        /// <param name="task">任务信息</param>
+        public static void updateRedisHash(this WCS_TaskInfo task)
+        {
+            RedisHub.WMS.HMSet($"Hash:{task.ID}", task.ToDic());
+        }
+
+        
+    }
+}

+ 12 - 0
成品库/WCS.WorkEngineering/Extensions/TrussExtebsion.cs

@@ -0,0 +1,12 @@
+using WCS.Core;
+using WCS.WorkEngineering.Protocol.Truss;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    public class Truss : Device<ITruss520, ITruss521, ITruss523, ITruss530, ITruss531>
+    {
+        public Truss(Device device, World world) : base(device, world)
+        {
+        }
+    }
+}

+ 95 - 0
成品库/WCS.WorkEngineering/Extensions/WorldExtension.cs

@@ -0,0 +1,95 @@
+using ServiceCenter.Logs;
+using WCS.Core;
+using LogInfo = ServiceCenter.Logs.LogInfo;
+
+namespace WCS.WorkEngineering.Extensions
+{
+    public static class WorldExtension
+    {
+        /// <summary>
+        ///  记录日志
+        ///  默认:低级别 已知 不上抛
+        /// </summary>
+        /// <param name="source">世界</param>
+        /// <param name="msg">消息</param>
+        public static void Log(this World source, string msg)
+        {
+            source.Log(new LogInfo { Level = LogLevelEnum.Low, Type = ErrorTypeEnum.Kown, LogUpLoad = LogUpLoadEnum.NotUpLoad, Message = msg });
+        }
+
+        /// <summary>
+        ///  记录日志
+        ///  默认:已知
+        ///  上抛根据日志级别决定:低级别不上抛,中高级别上抛WMS
+        /// </summary>
+        /// <param name="source">世界</param>
+        /// <param name="msg">消息</param>
+        /// <param name="level">日志级别</param>
+        public static void Log(this World source, string msg, LogLevelEnum level)
+        {
+            LogUpLoadEnum logUpLoad = LogUpLoadEnum.NotUpLoad;
+            switch (level)
+            {
+                case LogLevelEnum.Low:
+                    logUpLoad = LogUpLoadEnum.NotUpLoad;
+                    break;
+
+                case LogLevelEnum.Mid:
+                    logUpLoad = LogUpLoadEnum.UpLoadWMS;
+                    break;
+
+                case LogLevelEnum.High:
+                    logUpLoad = LogUpLoadEnum.UpLoadWMS;
+                    break;
+
+                default:
+                    break;
+            }
+            source.Log(new LogInfo { Level = level, Type = ErrorTypeEnum.Kown, LogUpLoad = logUpLoad, Message = msg });
+        }
+
+        /// <summary>
+        ///  记录日志
+        ///  上抛根据日志级别决定:低级别不上抛,中高级别上抛WMS
+        /// </summary>
+        /// <param name="source">世界</param>
+        /// <param name="msg">消息</param>
+        /// <param name="level">日志级别</param>
+        /// <param name="errorType">日志类型</param>
+        public static void Log(this World source, string msg, LogLevelEnum level, ErrorTypeEnum errorType)
+        {
+            LogUpLoadEnum logUpLoad = LogUpLoadEnum.NotUpLoad;
+            switch (level)
+            {
+                case LogLevelEnum.Low:
+                    logUpLoad = LogUpLoadEnum.NotUpLoad;
+                    break;
+
+                case LogLevelEnum.Mid:
+                    logUpLoad = LogUpLoadEnum.UpLoadWMS;
+                    break;
+
+                case LogLevelEnum.High:
+                    logUpLoad = LogUpLoadEnum.UpLoadWMS;
+                    break;
+
+                default:
+                    break;
+            }
+            source.Log(new LogInfo { Level = level, Type = errorType, LogUpLoad = logUpLoad, Message = msg });
+        }
+
+        /// <summary>
+        ///  记录日志
+        /// </summary>
+        /// <param name="source">世界</param>
+        /// <param name="msg">消息</param>
+        /// <param name="level">日志级别</param>
+        /// <param name="errorType">日志类型</param>
+        /// <param name="logUpLoad">日志上抛类型</param>
+        public static void Log(this World source, string msg, LogLevelEnum level, ErrorTypeEnum errorType, LogUpLoadEnum logUpLoad)
+        {
+            source.Log(new LogInfo { Level = level, Type = errorType, LogUpLoad = logUpLoad, Message = msg });
+        }
+    }
+}

+ 9 - 0
成品库/WCS.WorkEngineering/LockHub.cs

@@ -0,0 +1,9 @@
+namespace WCS.WorkEngineering
+{
+    public static class LockHub
+    {
+        public static object ApplyEmptySpoolLock = new object();
+
+        public static object AgvCallbackLock = new object();
+    }
+}

+ 17 - 0
成品库/WCS.WorkEngineering/Protocol/BCR/IBCR80.cs

@@ -0,0 +1,17 @@
+using System.ComponentModel.DataAnnotations;
+using WCS.Entity.Protocol.BCR;
+
+namespace WCS.WorkEngineering.Protocol.BCR
+{
+    /// <summary>
+    /// 扫码头协议80
+    /// </summary>
+    public interface IBCR80 : BCR80
+    {
+        /// <summary>
+        /// 内容
+        /// </summary>
+        [StringLength(20)]
+        new string Content { get; set; }
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/BCR/IBCR81.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.BCR;
+
+namespace WCS.WorkEngineering.Protocol.BCR
+{
+    /// <summary>
+    /// 扫码头协议81
+    /// </summary>
+    public interface IBCR81 : BCR81
+    {
+    }
+}

+ 51 - 0
成品库/WCS.WorkEngineering/Protocol/BCR/IBCR83.cs

@@ -0,0 +1,51 @@
+using System.ComponentModel.DataAnnotations;
+using WCS.Entity;
+
+namespace WCS.WorkEngineering.Protocol.BCR
+{
+    /// <summary>
+    ///  满轮主线读取
+    /// </summary>
+    public interface IBCR83 : IProtocol
+    {
+        public short index { get; set; }
+
+        public short Lastindex { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode1 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode2 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode3 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode4 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode5 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode6 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode7 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode8 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode9 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode10 { get; set; }
+
+        [StringLength(50)]
+        public string BcrCode11 { get; set; }
+    }
+}

+ 17 - 0
成品库/WCS.WorkEngineering/Protocol/BCR/WCS_BCR80.cs

@@ -0,0 +1,17 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.BCR
+{
+    /// <summary>
+    /// 读码器读取协议
+    /// </summary>
+    [DataContract]
+    public class WCS_BCR80 : IBCR80
+    {
+        /// <summary>
+        /// 内容
+        /// </summary>
+        [DataMember(Order = 0)]
+        public string Content { get; set; }
+    }
+}

+ 17 - 0
成品库/WCS.WorkEngineering/Protocol/BCR/WCS_BCR81.cs

@@ -0,0 +1,17 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.BCR
+{
+    /// <summary>
+    /// 读码器写入协议81
+    /// </summary>
+    [DataContract]
+    public class WCS_BCR81 : IBCR80
+    {
+        /// <summary>
+        /// 内容
+        /// </summary>
+        [DataMember(Order = 0)]
+        public string Content { get; set; }
+    }
+}

+ 17 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/BCRData.cs

@@ -0,0 +1,17 @@
+using System.Runtime.Serialization;
+using WCS.WorkEngineering.Protocol.BCR;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    ///  扫码器
+    /// </summary>
+    [DataContract]
+    public class BCRData : DeviceData
+    {
+        /// <summary>
+        ///  扫码结果
+        /// </summary>
+        public WCS_BCR81 Bcr81 { get; set; }
+    }
+}

+ 30 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/DeviceData.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    /// 设备数据基类
+    /// </summary>
+    [DataContract]
+    public class DeviceData
+    {
+        /// <summary>
+        /// 设备号
+        /// </summary>
+        [DataMember(Order = 0)]
+        public string Code { get; set; }
+
+        /// <summary>
+        /// 时间
+        /// </summary>
+        [DataMember(Order = 1)]
+        public DateTime Frame { get; set; }
+
+        /// <summary>
+        /// 信息
+        /// </summary>
+        [DataMember(Order = 2)]
+        public string Info { get; set; } = "";
+    }
+}

+ 44 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/DeviceDataCollection.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    /// 设备数据
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    [DataContract]
+    public class DeviceDataCollection<T> where T : DeviceData
+    {
+        /// <summary>
+        /// 确认时间
+        /// </summary>
+        [DataMember(Order = 3)]
+        public DateTime Frame { get; set; }
+
+        /// <summary>
+        /// 数据集
+        /// </summary>
+        [DataMember(Order = 4)]
+        public T[] Datas { get; set; }
+
+        /// <summary>
+        ///  默认构造函数
+        /// </summary>
+        public DeviceDataCollection()
+        {
+        }
+
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        /// <param name="frame"></param>
+        /// <param name="datas"></param>
+        public DeviceDataCollection(DateTime frame, object[] datas)
+        {
+            this.Frame = frame;
+            this.Datas = datas.OfType<T>().ToArray();
+        }
+    }
+}

+ 60 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/DeviceDataPack.cs

@@ -0,0 +1,60 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    ///  设备数据包
+    /// </summary>
+    [DataContract]
+    public class DeviceDataPack
+    {
+        /// <summary>
+        ///  堆垛机数据集
+        /// </summary>
+        [DataMember(Order = 0)]
+        public DeviceDataCollection<SRMData> SRMDatas { get; set; }
+
+        /// <summary>
+        ///  穿梭车数据集
+        /// </summary>
+        [DataMember(Order = 1)]
+        public DeviceDataCollection<RGVData> RGVDatas { get; set; }
+
+        /// <summary>
+        ///  站台数据集
+        /// </summary>
+        [DataMember(Order = 2)]
+        public DeviceDataCollection<StationData> StationDatas { get; set; }
+
+        ///// <summary>
+        /////  扫码器数据
+        ///// </summary>
+        //[DataMember(Order = 3)]
+        //public DeviceDataCollection<BCRData> BcrDatas { get; set; }
+
+        /// <summary>
+        ///  机器人数据集
+        /// </summary>
+        [DataMember(Order = 4)]
+        public DeviceDataCollection<RobotData> RobotData { get; set; }
+
+        /// <summary>
+        ///  产线数据集
+        /// </summary>
+        [DataMember(Order = 5)]
+        public DeviceDataCollection<ProdLineData> ProdLineData { get; set; }
+
+        /// <summary>
+        ///  时间
+        /// </summary>
+        [DataMember(Order = 6)]
+        public DateTime Frame { get; set; }
+
+        /// <summary>
+        /// 回放最早时间
+        /// </summary>
+        [DataMember(Order = 7)]
+        public int PlaybackSeconds { get; set; }
+    }
+}

+ 18 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/ProdLineData.cs

@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    /// 产线信息
+    /// </summary>
+    [DataContract]
+    public class ProdLineData : DeviceData
+    {
+        /// <summary>
+        ///  产线任务信息
+        /// </summary>
+        //[DataMember(Order = 3)]
+        //public List<WCS_AgvTaskInfo> TaskList { get; set; } = new List<WCS_AgvTaskInfo>();
+    }
+}

+ 17 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/RGVData.cs

@@ -0,0 +1,17 @@
+using System.Runtime.Serialization;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    [DataContract]
+    public class RGVData : DeviceData
+    {
+        //[DataMember(Order = 5)]
+        //public WCS_RGV520 D520 { get; set; }
+
+        //[DataMember(Order = 3)]
+        //public WCS_RGV521 D521 { get; set; }
+
+        //[DataMember(Order = 4)]
+        //public WCS_RGV523 D523 { get; set; }
+    }
+}

+ 14 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/RobotData.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    [DataContract]
+    public class RobotData : DeviceData
+    {
+        //[DataMember(Order = 3)]
+        //public WCS_Robot Data { get; set; }
+    }
+}

+ 31 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/SRMData.cs

@@ -0,0 +1,31 @@
+using System.Runtime.Serialization;
+using WCS.Entity.Protocol.SRM;
+using WCS.WorkEngineering.Protocol.SRM;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    ///  堆垛机数据
+    /// </summary>
+    [DataContract]
+    public class SRMData : DeviceData
+    {
+        /// <summary>
+        ///  DB520
+        /// </summary>
+        [DataMember(Order = 3)]
+        public WCS_SRM520 D520 { get; set; } = null!;
+
+        /// <summary>
+        ///  DB521
+        /// </summary>
+        [DataMember(Order = 4)]
+        public WCS_SRM521 D521 { get; set; } = null!;
+
+        /// <summary>
+        ///  DB523
+        /// </summary>
+        [DataMember(Order = 5)]
+        public WCS_SRM537 D537 { get; set; } = null!;
+    }
+}

+ 34 - 0
成品库/WCS.WorkEngineering/Protocol/DataStructure/StationData.cs

@@ -0,0 +1,34 @@
+using System.Runtime.Serialization;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.Station;
+
+namespace WCS.Entity.Protocol.DataStructure
+{
+    /// <summary>
+    ///  输送线数据
+    /// </summary>
+    [DataContract]
+    public class StationData : DeviceData
+    {
+        [DataMember(Order = 3)]
+        public WCS_Station520 D520 { get; set; }
+
+        [DataMember(Order = 4)]
+        public WCS_Station521 D521 { get; set; }
+
+        [DataMember(Order = 5)]
+        public WCS_Station523 D523 { get; set; }
+
+        [DataMember(Order = 6)]
+        public WCS_Station90 D90 { get; set; }
+
+        [DataMember(Order = 7)]
+        public WCS_Station91 D91 { get; set; }
+
+        [DataMember(Order = 8)]
+        public WCS_BCR80 D80 { get; set; }
+
+        [DataMember(Order = 9)]
+        public WCS_BCR81 D81 { get; set; }
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/RGV/IRGV520.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.RGV;
+
+namespace WCS.WorkEngineering.Protocol.RGV
+{
+    /// <summary>
+    ///  DB520
+    /// </summary>
+    public interface IRGV520 : RGV520<RGVCmdType>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/RGV/IRGV521.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.RGV;
+
+namespace WCS.WorkEngineering.Protocol.RGV
+{
+    /// <summary>
+    ///  RGV521
+    /// </summary>
+    public interface IRGV521 : RGV521<RGVCmdType, RGVSystemStatus, RGVWorkMode, RGVStatus>
+    {
+    }
+}

+ 269 - 0
成品库/WCS.WorkEngineering/Protocol/RGV/RGVEnum.cs

@@ -0,0 +1,269 @@
+using System.ComponentModel;
+
+namespace WCS.WorkEngineering.Protocol.RGV
+{
+    /// <summary>
+    ///  RGV指令类型
+    /// </summary>
+    public enum RGVCmdType : short
+    {
+        /// <summary>
+        /// 取货
+        /// </summary>
+        [Description("取货")]
+        PickGoods = 1,
+
+        /// <summary>
+        /// 放货
+        /// </summary>
+        [Description("放货")]
+        PutGoods = 2,
+
+        /// <summary>
+        /// 移动
+        /// </summary>
+        [Description("移动")]
+        Move = 3,
+
+        /// <summary>
+        ///  变更放货点
+        /// </summary>
+        [Description("变更放货点")]
+        ChangePutGoods = 4,
+
+        /// <summary>
+        ///  变更取货点
+        /// </summary>
+        [Description("变更取货点")]
+        ChangePickGoods = 5,
+
+        /// <summary>
+        ///  取放货
+        /// </summary>
+        [Description("取放货")]
+        PickPutGoods = 6
+    }
+
+    /// <summary>
+    ///  货叉式RGV状态
+    /// </summary>
+    public enum RGVSystemStatus : short
+    {
+        /// <summary>
+        /// 空闲
+        /// </summary>
+        [Description("空闲")]
+        空闲 = 0,
+
+        /// <summary>
+        /// 获取取货位
+        /// </summary>
+        [Description("获取取货位")]
+        获取取货位 = 1,
+
+        /// <summary>
+        /// 取货移动
+        /// </summary>
+        [Description("取货移动")]
+        取货移动 = 2,
+
+        /// <summary>
+        /// 到达取货位
+        /// </summary>
+        [Description("到达取货位")]
+        到达取货位 = 4,
+
+        /// <summary>
+        /// 取货伸叉
+        /// </summary>
+        [Description("取货伸叉")]
+        取货伸叉 = 5,
+
+        /// <summary>
+        /// 取货抬叉
+        /// </summary>
+        [Description("取货抬叉")]
+        取货抬叉 = 6,
+
+        /// <summary>
+        /// 取货收叉
+        /// </summary>
+        [Description("取货收叉")]
+        取货收叉 = 7,
+
+        /// <summary>
+        /// 取货完成
+        /// </summary>
+        [Description("取货完成")]
+        取货完成 = 8,
+
+        /// <summary>
+        /// 获取放货位
+        /// </summary>
+        [Description("获取放货位")]
+        获取放货位 = 9,
+
+        /// <summary>
+        /// 放货移动
+        /// </summary>
+        [Description("放货移动")]
+        放货移动 = 10,
+
+        /// <summary>
+        /// 放货收叉
+        /// </summary>
+        [Description("放货收叉")]
+        放货伸叉 = 11,
+
+        /// <summary>
+        /// 放货下降
+        /// </summary>
+        [Description("放货下降")]
+        放货下降 = 12,
+
+        /// <summary>
+        /// 放货收叉
+        /// </summary>
+        [Description("取货抬叉")]
+        放货收叉 = 13,
+
+        /// <summary>
+        /// 放货完成
+        /// </summary>
+        [Description("放货完成")]
+        放货完成 = 14,
+    }
+
+    /// <summary>
+    ///  RGV模式
+    /// </summary>
+    public enum RGVWorkMode : short
+    {
+        /// <summary>
+        ///  自动
+        /// </summary>
+        [Description("自动")]
+        Automatic = 1,
+
+        /// <summary>
+        ///  半自动
+        /// </summary>
+        [Description("半自动")]
+        SemiAutomatic = 2,
+
+        /// <summary>
+        ///  手动
+        /// </summary>
+        [Description("手动")]
+        Manual = 3,
+
+        /// <summary>
+        ///  保持维修
+        /// </summary>
+        [Description("保持维修")]
+        KeepInRepair = 4
+    }
+
+    /// <summary>
+    ///  RGV状态
+    /// </summary>
+    [Flags]
+    public enum RGVStatus : ushort
+    {
+        /// <summary>
+        ///  光电
+        /// </summary>
+        [Description("光电")]
+        PH_Status = 1 << 0,
+
+        /// <summary>
+        ///  RGV到站
+        /// </summary>
+        [Description("RGV到站")]
+        Arrival = 1 << 1,
+
+        /// <summary>
+        ///  任务完成
+        /// </summary>
+        [Description("任务完成")]
+        Taskfinishi = 1 << 2,
+
+        /// <summary>
+        ///  载货
+        /// </summary>
+        [Description("载货")]
+        Cargo = 1 << 3,
+
+        /// <summary>
+        ///  RGV输送线正转
+        /// </summary>
+        [Description("RGV输送线正转")]
+        Forward = 1 << 4,
+
+        /// <summary>
+        ///  RGV输送线反转
+        /// </summary>
+        [Description("RGV输送线反转")]
+        Reverse = 1 << 5,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES1 = 1 << 6,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES2 = 1 << 7,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES3 = 1 << 8,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES4 = 1 << 9,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES5 = 1 << 10,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES6 = 1 << 11,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES7 = 1 << 12,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES9 = 1 << 13,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES10 = 1 << 14,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        RES11 = 1 << 15,
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/ISRM520.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.SRM;
+
+namespace WCS.WorkEngineering.Protocol.SRM
+{
+    /// <summary>
+    ///  堆垛机DB520
+    /// </summary>
+    public interface ISRM520 : SRM520<SrmRunSpeed, SrmForkPosition, SrmTaskType>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/ISRM521.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.SRM;
+
+namespace WCS.WorkEngineering.Protocol.SRM
+{
+    /// <summary>
+    ///  堆垛机DB521
+    /// </summary>
+    public interface ISRM521 : SRM521<SrmStatus, SrmAutoStatus, SrmRunStatus, SrmRunSpeed, SrmForkPosition, SrmTaskType>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/ISRM537.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.SRM;
+
+namespace WCS.WorkEngineering.Protocol.SRM
+{
+    /// <summary>
+    ///  堆垛机DB523
+    /// </summary>
+    public interface ISRM537 : SRM537<SrmAlarm>
+    {
+    }
+}

+ 667 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/SrmEnum.cs

@@ -0,0 +1,667 @@
+using System.ComponentModel;
+
+namespace WCS.WorkEngineering.Protocol.SRM
+{
+    /// <summary>
+    /// 运行模式
+    /// </summary>
+    public enum SrmRunSpeed : short
+    {
+        /// <summary>
+        ///  默认
+        /// </summary>
+        [Description("默认")]
+        Default = 0,
+
+        /// <summary>
+        ///  低速
+        /// </summary>
+        [Description("低速")]
+        LowSpeed = 1,
+    }
+
+    /// <summary>
+    /// 任务类型
+    /// </summary>
+    public enum SrmTaskType : short
+    {
+        /// <summary>
+        ///  默认 出入库使用该任务类型
+        /// </summary>
+        [Description("默认,出入库使用该任务类型")]
+        Default = 0,
+
+        /// <summary>
+        ///  完成任务
+        /// </summary>
+        [Description("完成任务")]
+        FinishTask = 1,
+
+        /// <summary>
+        ///  删除任务
+        /// </summary>
+        [Description("删除任务")]
+        DeleteTask = 2,
+
+        /// <summary>
+        ///  移动任务
+        /// </summary>
+        [Description("移动任务")]
+        MoveTask = 3,
+
+        /// <summary>
+        ///  移库任务
+        /// </summary>
+        [Description("移库任务")]
+        MoveGoods = 4
+    }
+
+    /// <summary>
+    /// 货叉位置
+    /// </summary>
+    public enum SrmForkPosition : short
+    {
+        /// <summary>
+        ///  中位
+        /// </summary>
+        [Description("中位")]
+        Centr = 0,
+
+        /// <summary>
+        ///  一深度
+        /// </summary>
+        [Description("一深度")]
+        OneDepth = 1,
+
+        /// <summary>
+        /// 二深度
+        /// </summary>
+        [Description("二深度")]
+        TwoDepth = 2
+    }
+
+    /// <summary>
+    /// 运行模式
+    /// </summary>
+    public enum SrmAutoStatus : short
+    {
+        /// <summary>
+        ///  自动
+        /// </summary>
+        [Description("自动")]
+        Automatic = 1,
+
+        /// <summary>
+        ///  半自动
+        /// </summary>
+        [Description("半自动")]
+        SemiAutomatic = 2,
+
+        /// <summary>
+        ///  手动
+        /// </summary>
+        [Description("手动")]
+        Manual = 3,
+
+        /// <summary>
+        ///  保持维修
+        /// </summary>
+        [Description("保持维修")]
+        KeepInRepair = 4
+    }
+
+    /// <summary>
+    /// 运行状态
+    /// </summary>
+    public enum SrmRunStatus : short
+    {
+        /// <summary>
+        ///  空闲
+        /// </summary>
+        [Description("空闲")]
+        Idle = 1,
+
+        /// <summary>
+        ///  取货行走
+        /// </summary>
+        [Description("取货行走")]
+        GetGoodsWalk = 2,
+
+        /// <summary>
+        ///  取货伸叉
+        /// </summary>
+        [Description("取货伸叉")]
+        GetGoodsOutstretchFork = 3,
+
+        /// <summary>
+        ///  取货抬叉
+        /// </summary>
+        [Description("取货抬叉")]
+        GetGoodsLiftFork = 4,
+
+        /// <summary>
+        ///  取货收叉
+        /// </summary>
+        [Description("取货收叉")]
+        GetGoodsRetractFork = 5,
+
+        /// <summary>
+        ///  放货行走
+        /// </summary>
+        [Description("放货行走")]
+        PutGoodsWalk = 6,
+
+        /// <summary>
+        ///  放货伸叉
+        /// </summary>
+        [Description("放货伸叉")]
+        PutGoodsOutstretchFork = 7,
+
+        /// <summary>
+        ///  放货降叉
+        /// </summary>
+        [Description("放货降叉")]
+        PutGoodsDropFork = 8,
+
+        /// <summary>
+        ///  放货收叉
+        /// </summary>
+        [Description("放货收叉")]
+        PutGoodsRetractFork = 9,
+    }
+
+    /// <summary>
+    /// 堆垛机状态
+    /// </summary>
+    [Flags]
+    public enum SrmStatus : ushort
+    {
+        /// <summary>
+        ///  PLC的握手信号
+        /// </summary>
+        [Description("PLC的握手信号")]
+        HandshakeTowcs = 1 << 0,
+
+        /// <summary>
+        ///  完成取货信号
+        /// </summary>
+        [Description("完成取货信号")]
+        GetFinishi = 1 << 1,
+
+        /// <summary>
+        ///  完成放货信号
+        /// </summary>
+        [Description("完成放货信号")]
+        PutFinishi = 1 << 2,
+
+        /// <summary>
+        ///  报警信号
+        /// </summary>
+        [Description("报警信号")]
+        Alarm = 1 << 3,
+
+        /// <summary>
+        ///  任务完成信号
+        /// </summary>
+        [Description("任务完成信号")]
+        TaskFinish = 1 << 4,
+
+        /// <summary>
+        ///  设备有货
+        /// </summary>
+        [Description("设备有货")]
+        Loaded = 1 << 5,
+
+        /// <summary>
+        ///  货叉在原位
+        /// </summary>
+        [Description("货叉在原位")]
+        ForkCenter = 1 << 6,
+
+        /// <summary>
+        ///  可以下发任务
+        /// </summary>
+        [Description("可以下发任务")]
+        CanTaskIssued = 1 << 7,
+
+        /// <summary>
+        ///  单堆垛机是否可以跑全程
+        /// </summary>
+        [Description("单堆垛机是否可以跑全程")]
+        Stopper_Mark = 1 << 8,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+        [Description("保留")]
+        RES2 = 1 << 9,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+        [Description("保留")]
+        RES3 = 1 << 10,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+        [Description("保留")]
+        RES4 = 1 << 11,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+        [Description("保留")]
+        RES5 = 1 << 12,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+        [Description("保留")]
+        RES6 = 1 << 13,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+
+        [Description("保留")]
+        RES7 = 1 << 14,
+
+        /// <summary>
+        ///  保留
+        /// </summary>
+        [Description("保留")]
+        RES8 = 1 << 15,
+    }
+
+    /// <summary>
+    /// 堆垛机报警项
+    /// </summary>
+    [Flags]
+    public enum SrmAlarm : ulong
+    {
+        /// <summary>
+        ///  无
+        /// </summary>
+        [Description("无")]
+        无 = 0,
+
+        /// <summary>
+        ///  主柜急停
+        /// </summary>
+        [Description("主柜急停")]
+        主柜急停 = 1L << 0,
+
+        /// <summary>
+        ///  分柜急停
+        /// </summary>
+        [Description("分柜急停")]
+        分柜急停 = 1L << 1,
+
+        /// <summary>
+        ///  取货点异常双深位
+        /// </summary>
+        [Description("取货点异常双深位")]
+        取货点异常双深位 = 1L << 2,
+
+        /// <summary>
+        ///  放货点有货
+        /// </summary>
+        [Description("放货点有货")]
+        放货点有货 = 1L << 3,
+
+        /// <summary>
+        ///  货叉取货完成后无货
+        /// </summary>
+        [Description("货叉取货完成后无货")]
+        货叉取货完成后无货 = 1L << 4,
+
+        /// <summary>
+        ///  货叉无任务有货异常
+        /// </summary>
+        [Description("货叉无任务有货异常")]
+        货叉无任务有货异常 = 1L << 5,
+
+        /// <summary>
+        /// 货叉运行超时
+        /// </summary>
+        [Description("货叉运行超时")]
+        货叉运行超时 = 1L << 6,
+
+        /// <summary>
+        ///  货叉左侧超行程
+        /// </summary>
+        [Description("货叉左侧超行程")]
+        货叉左侧超行程 = 1L << 7,
+
+        /// <summary>
+        ///  货物左前坍塌
+        /// </summary>
+        [Description("货物左前坍塌")]
+        货物左前坍塌 = 1L << 8,
+
+        /// <summary>
+        ///  货物右前坍塌
+        /// </summary>
+        [Description("货物右前坍塌")]
+        货物右前坍塌 = 1L << 9,
+
+        /// <summary>
+        ///  前限位触发
+        /// </summary>
+        [Description("前限位触发")]
+        前限位触发 = 1L << 10,
+
+        /// <summary>
+        ///  后限位触发
+        /// </summary>
+        [Description("后限位触发")]
+        后限位触发 = 1L << 11,
+
+        /// <summary>
+        ///  上限位触发
+        /// </summary>
+        [Description("上限位触发")]
+        上限位触发 = 1L << 12,
+
+        /// <summary>
+        ///  下限位触发
+        /// </summary>
+        [Description("下限位触发")]
+        下限位触发 = 1L << 13,
+
+        /// <summary>
+        ///  超载限位触发
+        /// </summary>
+        [Description("超载限位触发")]
+        超载限位触发 = 1L << 14,
+
+        /// <summary>
+        ///  松绳限位触发1
+        /// </summary>
+        [Description("松绳限位触发1")]
+        松绳限位触发1 = 1L << 15,
+
+        /// <summary>
+        ///  行走运动超行程
+        /// </summary>
+        [Description("行走运动超行程")]
+        行走运动超行程 = 1L << 16,
+
+        /// <summary>
+        ///  起升运动超行程
+        /// </summary>
+        [Description("起升运动超行程")]
+        起升运动超行程 = 1L << 17,
+
+        /// <summary>
+        ///  行走变频器报警
+        /// </summary>
+        [Description("行走变频器报警")]
+        行走变频器报警 = 1L << 18,
+
+        /// <summary>
+        ///  提升变频器报警
+        /// </summary>
+        [Description("提升变频器报警")]
+        提升变频器报警 = 1L << 19,
+
+        /// <summary>
+        ///  货叉变频器报警
+        /// </summary>
+        [Description("货叉变频器报警")]
+        货叉变频器报警 = 1L << 20,
+
+        /// <summary>
+        ///  提升超速报警
+        /// </summary>
+        [Description("提升超速报警")]
+        提升超速报警 = 1L << 21,
+
+        /// <summary>
+        ///  风扇灯插座空开
+        /// </summary>
+        [Description("风扇灯插座空开")]
+        风扇灯插座空开 = 1L << 22,
+
+        /// <summary>
+        ///  触摸屏光通讯激光测距空开
+        /// </summary>
+        [Description("触摸屏光通讯激光测距空开")]
+        触摸屏光通讯激光测距空开 = 1L << 23,
+
+        /// <summary>
+        ///  行走马达保护器
+        /// </summary>
+        [Description("行走马达保护器")]
+        行走马达保护器 = 1L << 24,
+
+        /// <summary>
+        ///  行走抱闸空开
+        /// </summary>
+        [Description("行走抱闸空开")]
+        行走抱闸空开 = 1L << 25,
+
+        /// <summary>
+        ///  起升马达保护器
+        /// </summary>
+        [Description("起升马达保护器")]
+        起升马达保护器 = 1L << 26,
+
+        /// <summary>
+        ///  起升抱闸空开
+        /// </summary>
+        [Description("起升抱闸空开")]
+        起升抱闸空开 = 1L << 27,
+
+        /// <summary>
+        ///  货叉马达保护器
+        /// </summary>
+        [Description("货叉马达保护器")]
+        货叉马达保护器 = 1L << 28,
+
+        /// <summary>
+        ///  货叉抱闸空开
+        /// </summary>
+        [Description("货叉抱闸空开")]
+        货叉抱闸空开 = 1L << 29,
+
+        /// <summary>
+        ///  安全门打开
+        /// </summary>
+        [Description("安全门打开")]
+        安全门打开 = 1L << 30,
+
+        /// <summary>
+        ///  安全继电器报警
+        /// </summary>
+        [Description("安全继电器报警")]
+        安全继电器报警 = 1L << 31,
+
+        /// <summary>
+        ///  当前货位已禁用
+        /// </summary>
+        [Description("当前货位已禁用")]
+        当前货位已禁用 = 1L << 32,
+
+        /// <summary>
+        ///  组态中断报警
+        /// </summary>
+        [Description("组态中断报警")]
+        组态中断报警 = 1L << 33,
+
+        /// <summary>
+        ///  货物左前超出
+        /// </summary>
+        [Description("货物左前超出")]
+        货物左前超出 = 1L << 34,
+
+        /// <summary>
+        ///  货物左后超出
+        /// </summary>
+        [Description("货物左后超出")]
+        货物左后超出 = 1L << 35,
+
+        /// <summary>
+        ///  货物右前超出
+        /// </summary>
+        [Description("货物右前超出")]
+        货物右前超出 = 1L << 36,
+
+        /// <summary>
+        ///  货物右后超出
+        /// </summary>
+        [Description("货物右后超出")]
+        货物右后超出 = 1L << 37,
+
+        /// <summary>
+        ///  相序保护
+        /// </summary>
+        [Description("相序保护")]
+        相序保护 = 1L << 38,
+
+        /// <summary>
+        ///  备用
+        /// </summary>
+        [Description("备用")]
+        备用 = 1L << 39,
+
+        /// <summary>
+        ///  安全门1报警
+        /// </summary>
+        [Description("安全门1报警")]
+        安全门1报警 = 1L << 40,
+
+        /// <summary>
+        ///  安全门2报警
+        /// </summary>
+        [Description("安全门2报警")]
+        安全门2报警 = 1L << 41,
+
+        /// <summary>
+        ///  行走测距信号丢失报警
+        /// </summary>
+        [Description("行走测距信号丢失报警")]
+        行走测距信号丢失报警 = 1L << 42,
+
+        /// <summary>
+        ///  提升测距信号丢失报警
+        /// </summary>
+        [Description("提升测距信号丢失报警")]
+        提升测距信号丢失报警 = 1L << 43,
+
+        /// <summary>
+        ///  行走定位失败
+        /// </summary>
+        [Description("行走定位失败")]
+        行走定位失败 = 1L << 44,
+
+        /// <summary>
+        ///  提升定位失败
+        /// </summary>
+        [Description("提升定位失败")]
+        提升定位失败 = 1L << 45,
+
+        /// <summary>
+        ///  回中定位失败
+        /// </summary>
+        [Description("回中定位失败")]
+        回中定位失败 = 1L << 46,
+
+        /// <summary>
+        ///  堆垛机巷道有人进入光通讯中断
+        /// </summary>
+        [Description("堆垛机巷道有人进入光通讯中断")]
+        堆垛机巷道有人进入光通讯中断 = 1L << 47,
+
+        /// <summary>
+        ///  货叉位置错误
+        /// </summary>
+        [Description("货叉位置错误")]
+        货叉位置错误 = 1L << 48,
+
+        /// <summary>
+        ///  货叉编码器报警
+        /// </summary>
+        [Description("货叉编码器报警")]
+        货叉编码器报警 = 1L << 49,
+
+        /// <summary>
+        ///  货叉编码器报警中间位
+        /// </summary>
+        [Description("货叉编码器报警中间位")]
+        货叉编码器报警中间位 = 1L << 50,
+
+        /// <summary>
+        ///  货叉中位光电异常
+        /// </summary>
+        [Description("货叉中位光电异常")]
+        货叉中位光电异常 = 1L << 51,
+
+        /// <summary>
+        ///  载货台电源空开
+        /// </summary>
+        [Description("载货台电源空开")]
+        载货台电源空开 = 1L << 52,
+
+        /// <summary>
+        ///  按钮, 安全回路空开
+        /// </summary>
+        [Description("按钮安全回路空开")]
+        按钮安全回路空开 = 1L << 53,
+
+        /// <summary>
+        ///  货物左前坍塌
+        /// </summary>
+        [Description("货物左后坍塌")]
+        货物左后坍塌 = 1L << 54,
+
+        /// <summary>
+        ///  货物右前坍塌
+        /// </summary>
+        [Description("货物右后坍塌")]
+        货物右后坍塌 = 1L << 55,
+
+        /// <summary>
+        ///  登梯口急停
+        /// </summary>
+        [Description("登梯口急停")]
+        登梯口急停 = 1L << 56,
+
+        /// <summary>
+        ///  货物左超高19M
+        /// </summary>
+        [Description("货物左超高19M")]
+        货物左超高19M = 1L << 57,
+
+        /// <summary>
+        ///  货物右超高19M
+        /// </summary>
+        [Description("货物右超高19M")]
+        货物右超高19M = 1L << 58,
+
+        /// <summary>
+        ///  松绳限位触发2
+        /// </summary>
+        [Description("松绳限位触发2")]
+        松绳限位触发2 = 1L << 59,
+
+        /// <summary>
+        ///  货叉右侧超行程
+        /// </summary>
+        [Description("货叉右侧超行程")]
+        货叉右侧超行程 = 1L << 60,
+
+        /// <summary>
+        ///  取放货托盘总数超出限制
+        /// </summary>
+        [Description("取放货托盘总数超出限制")]
+        取放货托盘总数超出限制 = 1L << 61,
+
+        /// <summary>
+        ///  安全门急停
+        /// </summary>
+        [Description("安全门急停")]
+        安全门急停 = 1L << 62,
+    }
+}

+ 83 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/WCS_SRM520.cs

@@ -0,0 +1,83 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.SRM
+{
+    /// <summary>
+    ///  SRM520
+    /// </summary>
+    [DataContract]
+    public class WCS_SRM520 : ISRM520
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public short Res1 { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 1)]
+        public short Res2 { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 2)]
+        public short Res3 { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 3)]
+        public short GoodsType { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 4)]
+        public SrmRunSpeed RunSpeed { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 5)]
+        public short SLine { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 6)]
+        public short SCol { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 7)]
+        public short SLayer { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 8)]
+        public SrmForkPosition SDepth { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 9)]
+        public short ELine { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 10)]
+        public short ECol { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 11)]
+        public short ELayer { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 12)]
+        public SrmForkPosition EDepth { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 13)]
+        public int TaskNumber { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 14)]
+        public short VoucherNo { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 15)]
+        public short OkAck { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 16)]
+        public SrmTaskType TaskType { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 17)]
+        public short Cmd { get; set; }
+    }
+}

+ 128 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/WCS_SRM521.cs

@@ -0,0 +1,128 @@
+using System.Runtime.Serialization;
+using WCS.WorkEngineering.Protocol.SRM;
+
+namespace WCS.Entity.Protocol.SRM
+{
+    /// <summary>
+    ///  SRM521
+    /// </summary>
+    [DataContract]
+    public class WCS_SRM521 : ISRM521
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public SrmStatus Status { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 1)]
+        public SrmAutoStatus AutoStatus { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 2)]
+        public SrmRunStatus RunStatus { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 3)]
+        public short SLine { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 4)]
+        public short SCol { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 5)]
+        public short SLayer { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 6)]
+        public SrmForkPosition SDepth { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 7)]
+        public short ELine { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 8)]
+        public short ECol { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 9)]
+        public short ELayer { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 10)]
+        public SrmForkPosition EDepth { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 11)]
+        public int TaskNumber { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 12)]
+        public short VoucherNo { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 13)]
+        public short Line { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 14)]
+        public short Col { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 15)]
+        public short Layer { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 16)]
+        public int TaskFinishiId { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 17)]
+        public int TravelPos { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 18)]
+        public int LiftPos { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 19)]
+        public int ForkPos { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 20)]
+        public SrmRunSpeed RunSpeed { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 21)]
+        public SrmTaskType TaskType { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 22)]
+        public float TotalKm { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 23)]
+        public short GoodsType { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 24)]
+        public float RunTime { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 25)]
+        public int Res3 { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 26)]
+        public int Res4 { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 27)]
+        public int Res5 { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 28)]
+        public int Res6 { get; set; }
+    }
+}

+ 16 - 0
成品库/WCS.WorkEngineering/Protocol/SRM/WCS_SRM537.cs

@@ -0,0 +1,16 @@
+using System.Runtime.Serialization;
+using WCS.WorkEngineering.Protocol.SRM;
+
+namespace WCS.Entity.Protocol.SRM
+{
+    /// <summary>
+    ///  SRM537
+    /// </summary>
+    [DataContract]
+    public class WCS_SRM537 : ISRM537
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public SrmAlarm Alarm { get; set; }
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Station/IStation520.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Station;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    /// DB520
+    /// </summary>
+    public interface IStation520 : Station520<StationMode>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Station/IStation521.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Station;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    /// 输送机交互信号 读
+    /// </summary>
+    public interface IStation521 : Station521<StationMode>
+    {
+    }
+}

+ 62 - 0
成品库/WCS.WorkEngineering/Protocol/Station/IStation523.cs

@@ -0,0 +1,62 @@
+using System.ComponentModel;
+using WCS.Entity;
+using WCS.Entity.Protocol.Station;
+using static Dm.net.buffer.ByteArrayBuffer;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    /// 输送机状态读取协议
+    /// </summary>
+    public interface IStation523 : Station523<StationAlarm, StationStatus, StationStatus>
+    {
+    }
+
+    /// <summary>
+    /// 输送机状态读取协议
+    /// </summary>
+    public interface IStation524 : IProtocol
+    {
+        /// <summary>
+        ///  任务号
+        /// </summary>
+        [Description("任务号")]
+        int TaskNumber { get; set; }
+
+        /// <summary>
+        /// 起始地址
+        /// </summary>
+        [Description("起始地址")]
+        short GoodsStart { get; set; }
+
+        /// <summary>
+        /// 目标地址
+        /// </summary>
+        [Description("目标地址")]
+        short GoodsEnd { get; set; }
+
+        /// <summary>
+        /// 运行模式
+        /// </summary>
+        [Description("运行模式")]
+        StationMode Mode { get; set; }
+
+        /// <summary>
+        /// 指令回复
+        /// </summary>
+        [Description("指令回复")]
+        short CmdType { get; set; }
+
+        /// <summary>
+        /// 凭证号 每次累加
+        /// </summary>
+        [Description("凭证号")]
+        short VoucherNo { get; set; }
+
+        /// <summary>
+        /// 请求
+        /// </summary>
+        [Description("请求")]
+        short Request { get; set; }
+    }
+}

+ 8 - 0
成品库/WCS.WorkEngineering/Protocol/Station/IStation90.cs

@@ -0,0 +1,8 @@
+using WCS.Entity.Protocol.Station;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    public interface IStation90 : Station90
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Station/IStation91.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Station;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    /// 外检读取信息
+    /// </summary>
+    public interface IStation91 : Station91<StationShapeAlarm>
+    {
+    }
+}

+ 242 - 0
成品库/WCS.WorkEngineering/Protocol/Station/StationEnum.cs

@@ -0,0 +1,242 @@
+using System.ComponentModel;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    /// 输送机模式
+    /// </summary>
+    public enum StationMode : short
+    {
+        /// <summary>
+        /// 自动
+        /// </summary>
+        [Description("自动")]
+        Automatic = 1,
+
+        /// <summary>
+        /// 手动
+        /// </summary>
+        [Description("手动")]
+        Manual = 2,
+
+        /// <summary>
+        /// 维修
+        /// </summary>
+        [Description("维修")]
+        Repair = 3,
+    }
+
+    /// <summary>
+    /// 输送机警报
+    /// </summary>
+    [Flags]
+    public enum StationAlarm : ushort
+    {
+    }
+
+    /// <summary>
+    /// 输送机状态
+    /// </summary>
+    [Flags]
+    public enum StationStatus : ushort
+    {
+        /// <summary>
+        /// 自动
+        /// </summary>
+        [Description("自动")]
+        Auto = 1 << 0,
+
+        /// <summary>
+        /// 选中状态位
+        /// </summary>
+        [Description("选中状态位")]
+        Choice_Bit = 1 << 1,
+
+        /// <summary>
+        /// 任务有货
+        /// </summary>
+        [Description("任务有货")]
+        OT_Status = 1 << 2,
+
+        /// <summary>
+        /// 光电有货
+        /// </summary>
+        [Description("光电有货")]
+        PH_Status = 1 << 3,
+
+        /// <summary>
+        /// 运行状态位
+        /// </summary>
+        [Description("运行状态位")]
+        Run = 1 << 4,
+
+        /// <summary>
+        /// 正转
+        /// </summary>
+        [Description("正转")]
+        Fwd_1 = 1 << 5,
+
+        /// <summary>
+        /// 反转
+        /// </summary>
+        [Description("反转")]
+        Rev_1 = 1 << 6,
+
+        /// <summary>
+        /// 上升/右转/伸出(顶升移栽升降、拆码盘机升降、提升机升降、拆码盘机拨叉伸出)
+        /// </summary>
+        [Description("上升/右转/伸出(顶升移栽升降、拆码盘机升降、提升机升降、拆码盘机拨叉伸出)")]
+        Up_Right_Front_2 = 1 << 7,
+
+        /// <summary>
+        /// 下降/左转/缩回(顶升移栽升降、拆码盘机升降、提升机升降、拆码盘机拨叉缩回)
+        /// </summary>
+        [Description("下降/左转/缩回(顶升移栽升降、拆码盘机升降、提升机升降、拆码盘机拨叉缩回)")]
+        Down_Left_Back_2 = 1 << 8,
+
+        /// <summary>
+        /// 高位(顶升移栽升降、拆码盘机升降、提升机升降)
+        /// </summary>
+        [Description("高位(顶升移栽升降、拆码盘机升降、提升机升降)")]
+        High_Station_2 = 1 << 9,
+
+        /// <summary>
+        /// 中位(拆码盘机升降)
+        /// </summary>
+        [Description("中位(拆码盘机升降)")]
+        Mid_Station_2 = 1 << 10,
+
+        /// <summary>
+        /// 低位(顶升移栽升降、拆码盘机升降、提升机升降)
+        /// </summary>
+        [Description("低位(顶升移栽升降、拆码盘机升降、提升机升降)")]
+        Low_Station_2 = 1 << 11,
+
+        /// <summary>
+        /// 前位(拆码盘机拨叉伸出)
+        /// </summary>
+        [Description("前位(拆码盘机拨叉伸出)")]
+        Front_Station_2 = 1 << 12,
+
+        /// <summary>
+        /// 后位(拆码盘机拨叉缩回)
+        /// </summary>
+        [Description("后位(拆码盘机拨叉缩回)")]
+        Back_Station_2 = 1 << 13,
+
+        /// <summary>
+        /// 手动入库
+        /// </summary>
+        [Description("手动入库")]
+        ManualStorage = 1 << 14,
+
+        /// <summary>
+        /// 上位机未分配任务
+        /// </summary>
+        [Description("上位机未分配任务")]
+        UnassignedTask = 1 << 15,
+    }
+
+    /// <summary>
+    /// 外形故障
+    /// </summary>
+    [Flags]
+    public enum StationShapeAlarm : ushort
+    {
+        /// <summary>
+        /// 外形/条码等货物故障
+        /// </summary>
+        [Description("外形/条码等货物故障")]
+        Goods_Err = 1 >> 0,
+
+        /// <summary>
+        /// 前超长故障
+        /// </summary>
+        [Description("前超长故障")]
+        F_Outside = 1 >> 1,
+
+        /// <summary>
+        /// 后超长故障
+        /// </summary>
+        [Description("后超长故障")]
+        B_Outside = 1 >> 2,
+
+        /// <summary>
+        /// 左超宽故障
+        /// </summary>
+        [Description("左超宽故障")]
+        L_Outside = 1 >> 3,
+
+        /// <summary>
+        /// 右超宽故障
+        /// </summary>
+        [Description("右超宽故障")]
+        R_Outside = 1 >> 4,
+
+        /// <summary>
+        /// 超高故障
+        /// </summary>
+        [Description("超高故障")]
+        H_Outside = 1 >> 5,
+
+        /// <summary>
+        /// 条码读取失败
+        /// </summary>
+        [Description("条码读取失败")]
+        BCR_Noread = 1 >> 6,
+
+        /// <summary>
+        /// 超重
+        /// </summary>
+        [Description("超重")]
+        Overload = 1 >> 7,
+
+        /// <summary>
+        /// 货物严重外检故障
+        /// </summary>
+        [Description("货物严重外检故障")]
+        Goods_Err_1 = 1 >> 8,
+
+        /// <summary>
+        /// 二维条码未读出
+        /// </summary>
+        [Description("二维条码未读出")]
+        BCR_Noread_1 = 1 >> 9,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES1 = 1 >> 10,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES2 = 1 >> 11,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES3 = 1 >> 12,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES4 = 1 >> 13,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES5 = 1 >> 14,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES6 = 1 >> 15,
+    }
+}

+ 35 - 0
成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station520.cs

@@ -0,0 +1,35 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    ///  520
+    /// </summary>
+    [DataContract]
+    public class WCS_Station520 : IStation520
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public int TaskNumber { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 1)]
+        public short GoodsStart { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 2)]
+        public short GoodsEnd { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 3)]
+        public StationMode Mode { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 4)]
+        public short CmdType { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 5)]
+        public short VoucherNo { get; set; }
+    }
+}

+ 39 - 0
成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station521.cs

@@ -0,0 +1,39 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    ///  521
+    /// </summary>
+    [DataContract]
+    public class WCS_Station521 : IStation521
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public int TaskNumber { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 1)]
+        public short GoodsStart { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 2)]
+        public short GoodsEnd { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 3)]
+        public StationMode Mode { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 4)]
+        public short CmdType { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 5)]
+        public short VoucherNo { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 6)]
+        public short Request { get; set; }
+    }
+}

+ 31 - 0
成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station523.cs

@@ -0,0 +1,31 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    ///  523
+    /// </summary>
+    [DataContract]
+    public class WCS_Station523 : IStation523
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public StationAlarm Alarm { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 1)]
+        public short RES { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 2)]
+        public StationStatus Status { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 3)]
+        public float RunTime { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 4)]
+        public StationStatus Status1 { get; set; }
+    }
+}

+ 16 - 0
成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station90.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    ///  90
+    /// </summary>
+    [DataContract]
+    public class WCS_Station90 : IStation90
+    {
+
+    }
+}

+ 27 - 0
成品库/WCS.WorkEngineering/Protocol/Station/WCS_Station91.cs

@@ -0,0 +1,27 @@
+using System.Runtime.Serialization;
+
+namespace WCS.WorkEngineering.Protocol.Station
+{
+    /// <summary>
+    ///  91
+    /// </summary>
+    [DataContract]
+    public class WCS_Station91 : IStation91
+    {
+        /// <inheritdoc/>
+        [DataMember(Order = 0)]
+        public StationShapeAlarm ShapeAlarm { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 1)]
+        public float Weight { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 2)]
+        public float Length { get; set; }
+
+        /// <inheritdoc/>
+        [DataMember(Order = 3)]
+        public float Width { get; set; }
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Truss/ITruss520.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Truss;
+
+namespace WCS.WorkEngineering.Protocol.Truss
+{
+    /// <summary>
+    ///  桁架DB520 设备调度
+    /// </summary>
+    public interface ITruss520 : Truss520<short>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Truss/ITruss521.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Truss;
+
+namespace WCS.WorkEngineering.Protocol.Truss
+{
+    /// <summary>
+    ///  桁架DB521 设备调度
+    /// </summary>
+    public interface ITruss521 : Truss521<TrussStatus, short>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Truss/ITruss523.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Truss;
+
+namespace WCS.WorkEngineering.Protocol.Truss
+{
+    /// <summary>
+    ///  桁架DB523 设备调度
+    /// </summary>
+    public interface ITruss523 : Truss523<TrussAlarm>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Truss/ITruss530.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Truss;
+
+namespace WCS.WorkEngineering.Protocol.Truss
+{
+    /// <summary>
+    ///  桁架 码垛工位
+    /// </summary>
+    public interface ITruss530 : Truss530<TrussCmdType>
+    {
+    }
+}

+ 11 - 0
成品库/WCS.WorkEngineering/Protocol/Truss/ITruss531.cs

@@ -0,0 +1,11 @@
+using WCS.Entity.Protocol.Truss;
+
+namespace WCS.WorkEngineering.Protocol.Truss
+{
+    /// <summary>
+    /// 桁架 码垛工位 60工位版
+    /// </summary>
+    public interface ITruss531 : Truss531<TrussCmdType>
+    {
+    }
+}

+ 151 - 0
成品库/WCS.WorkEngineering/Protocol/Truss/TrussEnum.cs

@@ -0,0 +1,151 @@
+using System.ComponentModel;
+
+namespace WCS.WorkEngineering.Protocol.Truss
+{
+    /// <summary>
+    ///  桁架状态
+    /// </summary>
+    public enum TrussStatus : short
+    {
+        /// <summary>
+        ///  空闲
+        /// </summary>
+        [Description("空闲")]
+        Idle = 1,
+
+        /// <summary>
+        ///  执行中
+        /// </summary>
+        [Description("执行中")]
+        Execute = 2,
+
+        /// <summary>
+        ///  报警中
+        /// </summary>
+        [Description("报警中")]
+        Alarm = 3,
+
+        /// <summary>
+        ///  维护
+        /// </summary>
+        [Description("维护")]
+        KeepInRepair = 4,
+
+        /// <summary>
+        ///  手动
+        /// </summary>
+        [Description("手动")]
+        Manual = 5,
+    }
+
+    /// <summary>
+    /// 桁架报警项
+    /// </summary>
+    [Flags]
+    public enum TrussAlarm : ulong
+    {
+    }
+
+    /// <summary>
+    ///  桁架码垛位指令类型
+    /// </summary>
+    [Flags]
+    public enum TrussCmdType : ushort
+    {
+        /// <summary>
+        /// 码垛结束
+        /// </summary>
+        [Description("码垛结束")]
+        End = 1 >> 0,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES7 = 1 >> 1,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES8 = 1 >> 2,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES9 = 1 >> 3,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES10 = 1 >> 4,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES11 = 1 >> 5,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES12 = 1 >> 6,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES13 = 1 >> 7,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES14 = 1 >> 8,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES = 1 >> 9,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES1 = 1 >> 10,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES2 = 1 >> 11,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES3 = 1 >> 12,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES4 = 1 >> 13,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES5 = 1 >> 14,
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        [Description("备用")]
+        RES6 = 1 >> 15,
+    }
+}

+ 76 - 0
成品库/WCS.WorkEngineering/ProtocolProxy.cs

@@ -0,0 +1,76 @@
+using MessagePack;
+using Newtonsoft.Json;
+using ServiceCenter;
+using ServiceCenter.Redis;
+using WCS.Core;
+using WCS.Entity.Protocol.DataStructure;
+
+namespace WCS.Service
+{
+    public class ProtocolProxy : ProtocolProxyBase
+    {
+        public static DeviceDataPack DataPack { get; set; } = new DeviceDataPack();
+
+        public ProtocolProxy(Device dev, ProtocolInfo info, Type protocolType, World world) : base(dev, info, protocolType, world)
+        {
+            #region 初始化Redis连接
+
+            var redisConnectionStrings = RedisHub.Default.Check("RedisConnectionStrings") ?? throw new Exception("请在Redis中配置RedisConnectionStrings");
+            var configs = JsonConvert.DeserializeObject<List<DataBaseConnectionString>>(redisConnectionStrings);
+            if (configs != null)
+            {
+                if (configs.All(v => v.Key != "Monitor")) throw new Exception("请在RedisConnectionStrings中配置监控RedisDB库连接字符串");
+            }
+
+            foreach (var redisConnection in configs!)
+            {
+                RedisHub.CreateContext(redisConnection.ConnectionString, redisConnection.Key);
+                switch (redisConnection.Key)
+                {
+                    case "Monitor":
+                        RedisHub.SetMonitorContextType(redisConnection.Key);
+                        RedisHub.Monitor.Serialize = obj =>
+                        {
+                            var bytes = MessagePackSerializer.Serialize(obj);
+                            return bytes;
+                        };
+                        RedisHub.Monitor.DeserializeRaw = (bytes, type) =>
+                        {
+                            var obj = MessagePackSerializer.Deserialize(type, bytes);
+                            return obj;
+                        };
+                        break;
+
+                    case "DebugRedisUrl":
+                        RedisHub.SetDebugContextType(redisConnection.Key);
+                        Configs.DebugRedisUrl = redisConnection.ConnectionString;
+                        break;
+
+                    case "WMS":
+                        RedisHub.SetWMSContextType(redisConnection.Key);
+                        break;
+                }
+            }
+
+            #endregion 初始化Redis连接
+        }
+
+        protected override void DataChanged()
+        {
+        }
+
+        private object Copy(object obj, Type type)
+        {
+            var res = Activator.CreateInstance(type);
+            foreach (var p in type.GetProperties())
+            {
+                var p2 = obj.GetType().GetProperty(p.Name);
+                if (p2 != null && p2.PropertyType == p.PropertyType)
+                {
+                    p.SetValue(res, p2.GetValue(obj));
+                }
+            }
+            return res;
+        }
+    }
+}

+ 274 - 0
成品库/WCS.WorkEngineering/Systems/AgvSystems.cs

@@ -0,0 +1,274 @@
+using PlcSiemens.Core.Extension;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.WebApi.Controllers;
+using WCS.WorkEngineering.Worlds;
+using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  Agv交互系统
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("Agv交互系统")]
+    public class AgvSystems : DeviceSystem<Station>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        private List<Station> devs = new List<Station>();
+        private List<SRM> srms = new List<SRM>();
+
+        public AgvSystems()
+        {
+            devs = Device.All.Where(v => v.HasFlag(DeviceFlags.入库, DeviceFlags.巷道口)).Select(v => new Station(v, this.World)).ToList();
+            srms = Device.All.Where(v => v.HasProtocol(typeof(ISRM520))).Select(v => new SRM(v, this.World)).ToList();
+        }
+
+        public override void Do(Station obj)
+        {
+            if (obj.Entity.HasFlag(DeviceFlags.出库))
+            {
+                List<WCS_AgvTaskInfo> agvTaskInfos = new List<WCS_AgvTaskInfo>();
+                //获取所有未结束的叫料及背负式补空AGV任务
+                SqlSugarHelper.Do(db =>
+                {
+                    agvTaskInfos = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => (v.TaskType == AGVTaskType.CallMaterial || v.TaskType == AGVTaskType.CallForMaterial || v.TaskType == AGVTaskType.ForkliftFilling))
+                                                                         .Where(v => v.Status < AGVTaskStatus.MissionCompleted)
+                                                                         .SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.AddTime).ToList();
+                });
+                //有需要处理的AGV任务
+                if (agvTaskInfos.Any())
+                {
+                    this.ExRecord(obj.Entity.Code, "可用出库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList());
+                    List<WCS_TaskInfo> taskInfos = new List<WCS_TaskInfo>();
+
+                    foreach (var agv in agvTaskInfos)
+                    {
+                        try
+                        {
+                            SqlSugarHelper.Do(db =>
+                            {
+                                //取货点安全交互
+                                if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission2 && agv.Status != AGVTaskStatus.Complete2)
+                                {
+                                    var taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agv.ID);
+                                    agv.Status = AGVTaskStatus.Complete2;
+                                    db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                    taskInfo.AddWCS_TASK_DTL(db, "agv", $"允许AGV任务{agv.ID}在站台{agv.Station}取货");
+                                    AgvApi.ContinueTask(agv.AgvID, agv.Station);
+                                }
+                                //完成任务
+                                else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted)
+                                {
+                                    if (agv.TaskType is AGVTaskType.CallForMaterial or AGVTaskType.ForkliftFilling or AGVTaskType.CallMaterial)
+                                    {
+                                        var taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agv.ID);
+                                        if (taskInfo == null) throw new Exception($"未找到AGV任务{agv.ID}对应WCS任务");
+                                        //更新AGV任务状态
+                                        agv.Status = AGVTaskStatus.MissionCompleted;
+                                        db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                        //更新WCS任务状态
+                                        taskInfo.Status = Entity.TaskStatus.Finish;
+                                        taskInfo.EedTime = DateTime.Now;
+                                        db.Default.Updateable(taskInfo).ExecuteCommand();
+                                        taskInfo.AddWCS_TASK_DTL(db, "agv", "任务完成");
+                                        taskInfo.CompleteOrCancelTasks(db);
+                                        taskInfos.Add(taskInfo);
+                                    }
+                                    else
+                                    {
+                                        agv.Status = AGVTaskStatus.MissionCompleted;
+                                        db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                    }
+                                }
+                            });
+                        }
+                        catch (Exception ex)
+                        {
+                            World.Log(ex.Message, LogLevelEnum.Mid);
+                            this.ExRecord(obj.Entity.Code, ex.Message);
+                            continue;
+                        }
+                    }
+
+                    foreach (var item in taskInfos)
+                    {
+                        WmsApi.CompleteTask(item.ID);
+                    }
+                }
+            }
+            else if (obj.Entity.HasFlag(DeviceFlags.入库))
+            {
+                List<WCS_AgvTaskInfo> agvTaskInfos = new List<WCS_AgvTaskInfo>();
+                //获取所有未结束的入库AGV任务
+                SqlSugarHelper.Do(db =>
+                {
+                    agvTaskInfos = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot).SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.EditTime).ToList();
+                });
+
+                if (agvTaskInfos.Any())
+                {
+                    this.ExRecord(obj.Entity.Code, "可用入库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList());
+                    foreach (var agv in agvTaskInfos)
+                    {
+                        try
+                        {
+                            SqlSugarHelper.Do(db =>
+                            {
+                                //找到对应WCS任务
+                                var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.AgvTaskID == agv.ID);
+                                if (task == null) throw new Exception($"AGV任务{agv.ID}未找到对应WCS任务");
+
+                                #region 开始跟据AGV状态做出处理
+
+                                //巷道分配
+                                if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission1 && agv.Status != AGVTaskStatus.Complete1)
+                                {
+                                    this.ExRecord(obj.Entity.Code, $"AGV任务{agv.ID}开始进行巷道分配");
+                                    //向WMS获取巷道优先级
+                                    var res = WmsApi.GetTunnelPriorityList(task.ID);
+                                    this.ExRecord(obj.Entity.Code, $"AGV任务{agv.ID},WMS返回巷道优先级{res.ResData}");
+                                    var tunnelNo = res.ResData.Split(",").Select(v => "SRM" + v).ToList();
+
+                                    //开始获取堆垛机与可用站台信息
+                                    SRM srm = null;
+                                    List<Station> stations = new List<Station>();
+                                    if (task.Floor == 1) //一楼
+                                    {
+                                        //一楼三个入库口
+                                        stations = devs.Where(v => v.Entity.Code is "1011" or "1013" or "1015").ToList();
+                                        //筛选出可用站台
+                                        stations = stations.Where(v => v.Data.VoucherNo == v.Data2.VoucherNo && v.Data3.Status.HasFlag(StationStatus.Auto))
+                                                           .Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.OT_Status))
+                                                           .Where(v => !v.Data3.Status.HasFlag(StationStatus.Run)).ToList(); // 筛选出可用站台
+                                        this.ExRecord(obj.Entity.Code, $"AGV任务{agv.ID},可用放货站台", stations.Select(v => v.Entity.Code).ToList());
+                                        //可用堆垛机
+                                        srm = stations.Select(v => v.Entity.Sources).SelectMany(v => v).Where(v => v.IsTunnel()) //上一个地址是巷道的
+                                                      .Select(v => v.Sources).SelectMany(v => v).Where(v => v.HasProtocol(typeof(ISRM520))) //筛选出堆垛机
+                                                      .Select(v => new SRM(v, this.World)) //转换为SRM
+                                                      .Where(v => v != null && !v.Data2.Status.HasFlag(SrmStatus.Alarm) && v.Data2.AutoStatus == SrmAutoStatus.Automatic) //筛选出可用堆垛机
+                                                      .Where(v => tunnelNo.Contains(v.Entity.Code)) //筛选出巷道优先级最高的堆垛机
+                                                      .MinBy(v => tunnelNo.IndexOf(v.Entity.Code));//按照巷道优先级排序
+                                    }
+                                    else //二楼
+                                    {
+                                        //二楼三个入库口
+                                        stations = devs.Where(v => v.Entity.Code is "1021" or "1023" or "1025").ToList();
+                                        //筛选出可用站台
+                                        stations = stations.Where(v => v.Data.VoucherNo == v.Data2.VoucherNo && v.Data3.Status.HasFlag(StationStatus.Auto))
+                                                           .Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.OT_Status))
+                                                           .Where(v => !v.Data3.Status.HasFlag(StationStatus.Run)).ToList(); // 筛选出可用站台
+                                        this.ExRecord(obj.Entity.Code, $"AGV任务{agv.ID},可用放货站台", stations.Select(v => v.Entity.Code).ToList());
+                                        //可用堆垛机
+                                        srm = stations.Select(v => v.Entity.Sources).SelectMany(v => v).Where(v => v.IsTunnel()) //上一个地址是巷道的
+                                                      .Select(v => v.Sources).SelectMany(v => v).Where(v => v.HasProtocol(typeof(ISRM520))) //筛选出堆垛机
+                                                      .Select(v => new SRM(v, this.World)) //转换为SRM
+                                                      .Where(v => v != null && !v.Data2.Status.HasFlag(SrmStatus.Alarm) && v.Data2.AutoStatus == SrmAutoStatus.Automatic) //筛选出可用堆垛机
+                                                      .Where(v => tunnelNo.Contains(v.Entity.Code)) //筛选出巷道优先级最高的堆垛机
+                                                      .MinBy(v => tunnelNo.IndexOf(v.Entity.Code));//按照巷道优先级排序
+                                    }
+                                    if (srm == null) throw new Exception($"agv任务{agv.ID}无可用堆垛机");
+
+                                    //筛选出堆垛机的放货站台
+                                    var nextPos = stations.FirstOrDefault(v => v.Entity.Sources.Where(t => t.IsTunnel()).Select(t => t.Sources).SelectMany(v => v) //获取所有巷道
+                                                                                               .Where(t => t.HasProtocol(typeof(ISRM520)))//筛选出堆垛机
+                                                                                               .SelectMany(v => v.Sources).Any(t => t.Code == srm.Entity.Parent.Code));
+                                    this.ExRecord(obj.Entity.Code, $"AGV任务{agv.ID},放货站台{nextPos}");
+
+                                    bool flag = false;
+                                    if (((task.BusType == "二楼湿拉线退料回立库" || task.BusType == "二楼湿拉线余料回立库") && task.Floor == 2))
+                                    {
+                                        flag = true;
+                                        nextPos.Entity.Code = "1025";
+                                    }
+                                    var agvs = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.Position == nextPos.Entity.Code).SplitTable(v => v.Take(2)).ToList();
+                                    if (agvs.Any())
+                                    {
+                                        var msg = "已无可用放货站台,任务正在执行中:";
+                                        foreach (var ag in agvs)
+                                        {
+                                            msg = msg + $"[任务号:{ag.ID},目标地址:{ag.Position}]";
+                                        }
+                                        throw new Exception(msg);
+                                    }
+
+                                    //更新AGV任务状态
+                                    agv.Status = AGVTaskStatus.Complete1;
+                                    agv.Position = flag == true ? "1025" : nextPos.Entity.Code;
+                                    db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                    //更新WCS任务状态
+                                    if (flag)
+                                    {
+                                        srm.Entity.Code = "SRM3";
+                                        task.Device = srm.Entity.Code;
+                                        task.Tunnel = "3";
+                                        task.AddrNext = "1025";
+                                    }
+                                    else
+                                    {
+                                        task.Device = srm.Entity.Code;
+                                        task.Tunnel = task.Device.GetLastDigit().ToString();
+                                        task.AddrNext = agv.Position;
+                                    }
+                                    db.Default.Updateable(task).ExecuteCommand();
+                                    task.AddWCS_TASK_DTL(db, "AGV巷道分配点", nextPos.Entity.Code, $"任务分配至堆垛机:{srm.Entity.Code}");
+                                    this.ExRecord(obj.Entity.Code, $"AGV任务{agv.ID}分配至堆垛机:{srm.Entity.Code}");
+                                    //调继续执行任务接口
+                                    AgvApi.ContinueTask(agv.AgvID, nextPos.Entity.Code);
+                                }
+                                //放货站点安全交互
+                                else if (agv.AgvStatus == AGVTaskStatus.RequestOrPermission2 && agv.Status != AGVTaskStatus.Complete2)
+                                {
+                                    if (agv.Position.IsNullOrEmpty()) throw new Exception($"无有效放货地址");
+                                    var dev = devs.Find(v => v.Entity.Code == agv.Position);
+
+                                    if (dev.Data.VoucherNo != dev.Data2.VoucherNo) throw new Exception($"AGV请求放货,但{dev.Entity.Code}凭证号不一致");
+                                    if (!dev.Data3.Status.HasFlag(StationStatus.Auto)) throw new Exception($"AGV请求放货,但{dev.Entity.Code}不在自动状态");
+                                    if (dev.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new Exception($"AGV请求放货,但{dev.Entity.Code}光电有货");
+                                    if (dev.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new Exception($"AGV请求放货,但{dev.Entity.Code}任务有货");
+                                    if (dev.Data3.Status.HasFlag(StationStatus.Run)) throw new Exception($"AGV请求放货,但{dev.Entity.Code}在运行状态");
+                                    agv.Status = AGVTaskStatus.Complete2;
+                                    db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+
+                                    //调继续执行任务接口
+                                    AgvApi.ContinueTask(agv.AgvID, dev.Entity.Code);
+
+                                    dev.Data.TaskNumber = task.ID;
+                                }
+                                //完成任务
+                                else if (agv.AgvStatus == AGVTaskStatus.MissionCompleted && agv.Status != AGVTaskStatus.MissionCompleted)
+                                {
+                                    agv.Status = AGVTaskStatus.MissionCompleted;
+                                    db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                }
+
+                                #endregion 开始跟据AGV状态做出处理
+                            });
+                        }
+                        catch (Exception ex)
+                        {
+                            World.Log(ex.Message, LogLevelEnum.Mid);
+                            this.ExRecord(obj.Entity.Code, ex.Message);
+                            continue;
+                        }
+                    }
+                }
+            }
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code is "1011" or "1012";
+        }
+    }
+}

+ 155 - 0
成品库/WCS.WorkEngineering/Systems/DataCollectionSysyem.cs

@@ -0,0 +1,155 @@
+using Newtonsoft.Json;
+using ServiceCenter.Extensions;
+using ServiceCenter.Redis;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity.Protocol.DataStructure;
+using WCS.Entity.Protocol.SRM;
+using WCS.Service.Worlds;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Protocol.Station;
+
+namespace WCS.Service.Systems
+{
+    /// <summary>
+    ///  数据采集系统
+    /// </summary>
+    //[BelongTo(typeof(DataCollectionWorld))]
+    [Description("数据采集系统")]
+    public class DataCollectionSysyem : DeviceSystem<SRM>
+    {
+        public List<Station> ConvList;
+        public List<Device<IStation91>> Conv91List;
+        public List<Device<IBCR81>> Bcrs;
+        public List<SRM> Srms;
+
+        public DataCollectionSysyem()
+        {
+            ConvList = Device.All.Where(v => v.HasProtocol(typeof(IStation523))).Select(v => new Station(v, this.World)).ToList();
+            Conv91List = Device.All.Where(v => v.HasProtocol(typeof(IStation91))).Select(v => new Device<IStation91>(v, this.World)).ToList();
+            Bcrs = Device.All.Where(v => v.HasProtocol(typeof(IBCR81))).Select(v => new Device<IBCR81>(v, this.World)).ToList();
+            Srms = Device.All.Where(v => v.HasProtocol(typeof(ISRM520))).Select(v => new SRM(v, this.World)).ToList();
+        }
+
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "SRM1";
+        }
+
+        public override void Do(SRM obj)
+        {
+            try
+            {
+                DeviceDataPack pack = new DeviceDataPack();
+
+                //处理输送线
+                List<StationData> DevList = new List<StationData>();
+                foreach (var item in ConvList)
+                {
+                    var dev = new StationData()
+                    {
+                        Code = item.Entity.Code,
+                        Frame = DateTime.Now,
+                        D520 = TypeExtension.Mapper<WCS_Station520, IStation520>(item.Data),
+                        D521 = TypeExtension.Mapper<WCS_Station521, IStation521>(item.Data2),
+                        D523 = TypeExtension.Mapper<WCS_Station523, IStation523>(item.Data3),
+                        D90 = new WCS_Station90(),
+                        D91 = new WCS_Station91(),
+                        D80 = new WCS_BCR80(),
+                        D81 = new WCS_BCR81()
+                    };
+                    if (Conv91List.Any(v => v.Entity.Code == item.Entity.Code))
+                    {
+                        var d91 = Conv91List.First(v => v.Entity.Code == item.Entity.Code);
+                        dev.D91 = TypeExtension.Mapper<WCS_Station91, IStation91>(d91.Data);
+                    }
+                    if (Bcrs.Any(v => v.Entity.Code == item.Entity.Code))
+                    {
+                        var d81 = Bcrs.First(v => v.Entity.Code == item.Entity.Code);
+                        dev.D81 = TypeExtension.Mapper<WCS_BCR81, IBCR81>(d81.Data);
+                    }
+                    //保存报警
+                    RedisHub.WMS.Set($"{nameof(EquipmentAlarm)}:{item.Entity.Code}", JsonConvert.SerializeObject(new EquipmentAlarm()
+                    {
+                        Code = item.Entity.Code,
+                        Msg = item.Data3.Alarm.ToString(),
+                        Time = DateTime.Now
+                    }));
+
+                    DevList.Add(dev);
+                }
+                //保存模式
+                var status = ConvList.Select(v => new Tuple<string, string>(v.Entity.Code, v.Data2.Mode.ToString()));
+                RedisHub.WMS.Set($"ConvStatus", JsonConvert.SerializeObject(status));
+                pack.StationDatas = new DeviceDataCollection<StationData>(DateTime.Now, DevList.ToArray());
+
+                //处理堆垛机
+                List<SRMData> srmList = new List<SRMData>();
+                foreach (var item in Srms)
+                {
+                    var dev = new SRMData()
+                    {
+                        Code = item.Entity.Code,
+                        Frame = DateTime.Now,
+                        D520 = TypeExtension.Mapper<WCS_SRM520, ISRM520>(item.Data),
+                        D521 = TypeExtension.Mapper<WCS_SRM521, ISRM521>(item.Data2),
+                        D537 = TypeExtension.Mapper<WCS_SRM537, ISRM537>(item.Data3),
+                    };
+
+                    //保存报警
+                    RedisHub.WMS.Set($"{nameof(EquipmentAlarm)}:{item.Entity.Code}", JsonConvert.SerializeObject(new EquipmentAlarm()
+                    {
+                        Code = item.Entity.Code,
+                        Msg = item.Data3.Alarm.ToString(),
+                        Time = DateTime.Now
+                    }));
+                    srmList.Add(dev);
+                }
+                //保存模式
+                var status1 = Srms.Select(v => new Tuple<string, string>(v.Entity.Code, v.Data2.AutoStatus.ToString()));
+                RedisHub.WMS.Set($"SrmStatus", JsonConvert.SerializeObject(status1));
+                pack.SRMDatas = new DeviceDataCollection<SRMData>(DateTime.Now, srmList.ToArray());
+                pack.Frame = DateTime.Now;
+
+                //保存到Redis
+                RedisHub.Monitor.RPush("Packs", pack);
+                RedisHub.Monitor.Set(nameof(DeviceDataPack), pack);
+                if (RedisHub.Monitor.LLen("Packs") > 500000)
+                {
+                    RedisHub.Monitor.LTrim("Packs", 5000, -1);
+                }
+            }
+            catch (Exception ex)
+            {
+                World.Log(ex.StackTrace, ServiceCenter.Logs.LogLevelEnum.Mid);
+            }
+        }
+    }
+
+    /// <summary>
+    ///  设备报警
+    /// </summary>
+    public class EquipmentAlarm
+    {
+        /// <summary>
+        ///  设备号
+        /// </summary>
+        public string Code { get; set; }
+
+        /// <summary>
+        ///  内容
+        /// </summary>
+        public string Msg { get; set; }
+
+        /// <summary>
+        ///  时间
+        /// </summary>
+        public DateTime Time { get; set; }
+    }
+}

+ 127 - 0
成品库/WCS.WorkEngineering/Systems/DeviceWriteSystem.cs

@@ -0,0 +1,127 @@
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  设备信息写入接口
+    /// </summary>
+    //[BelongTo(typeof(MainWorld))]
+    public class DeviceWriteSystem : ServiceSystem<DeviceWriteInfo>
+    {
+        /// <summary>
+        /// 所有的站台
+        /// </summary>
+        private Dictionary<string, Station> Convs;
+
+        private Dictionary<string, SRM> Srms;
+
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        public DeviceWriteSystem()
+        {
+            Convs = Device.All.Where(v => v.HasProtocol<IStation523>()).Select(v => new Station(v, this.World)).ToDictionary(v => v.Entity.Code, v => v);
+            Srms = Device.All.Where(v => v.HasProtocol<ISRM520>()).Select(v => new SRM(v, this.World)).ToDictionary(v => v.Entity.Code, v => v);
+        }
+
+        protected override void Do(DeviceWriteInfo info)
+        {
+            Type? type = null;
+            object? obj = null;
+            switch (info.DeviceType)
+            {
+                case DeviceTypeEnum.SRM:
+                    var srm = Srms[info.Code];
+                    type = typeof(ISRM520).Assembly.GetTypes().Where(v => v.Name == info.Protocol).First();
+                    obj = srm.Entity.Protocol(type, this.World);
+
+                    break;
+
+                case DeviceTypeEnum.DEV:
+                    var conv = Convs[info.Code];
+                    type = typeof(IStation523).Assembly.GetTypes().Where(v => v.Name == info.Protocol).First();
+                    obj = conv.Entity.Protocol(type, this.World);
+
+                    break;
+
+                case DeviceTypeEnum.BCR:
+                    break;
+
+                case DeviceTypeEnum.RGV:
+                    break;
+            }
+            var p = type.GetProperty(info.Property);
+            if (p.PropertyType.IsEnum)
+            {
+                var value = Enum.Parse(p.PropertyType, info.Value);
+                p.SetValue(obj, value);
+            }
+            else
+            {
+                var value = Convert.ChangeType(info.Value, p.PropertyType);
+                p.SetValue(obj, value);
+            }
+        }
+    }
+
+    /// <summary>
+    /// 设备写入信息
+    /// </summary>
+    public class DeviceWriteInfo
+    {
+        /// <summary>
+        ///  设备类型
+        /// </summary>
+        public DeviceTypeEnum DeviceType { get; set; }
+
+        /// <summary>
+        /// 设备号
+        /// </summary>
+        public string Code { get; set; }
+
+        /// <summary>
+        ///  协议
+        /// </summary>
+        public string Protocol { get; set; }
+
+        /// <summary>
+        /// 字段明
+        /// </summary>
+        public string Property { get; set; }
+
+        /// <summary>
+        ///  值
+        /// </summary>
+        public string Value { get; set; }
+    }
+
+    /// <summary>
+    ///  设备类型接口
+    /// </summary>
+    public enum DeviceTypeEnum
+    {
+        /// <summary>
+        ///  堆垛机
+        /// </summary>
+        SRM = 1,
+
+        /// <summary>
+        ///  输送线
+        /// </summary>
+        DEV = 2,
+
+        /// <summary>
+        ///  扫码器
+        /// </summary>
+        BCR = 3,
+
+        /// <summary>
+        /// RGV小车
+        /// </summary>
+        RGV = 4,
+    }
+}

+ 65 - 0
成品库/WCS.WorkEngineering/Systems/GetDeviceSystem.cs

@@ -0,0 +1,65 @@
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  设备信息读取接口
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    public class GetDeviceSystem : ServiceSystem<Tuple<string, string>, object>
+    {
+        /// <summary>
+        /// 所有的站台
+        /// </summary>
+        private List<Station> Convs;
+
+        private List<SRM> Srms;
+
+        private List<BCR> Bcrs;
+
+        private List<Device<IStation523>> Device91;
+
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        public GetDeviceSystem()
+        {
+            //Convs = Device.All.Where(v => v.HasProtocol<IStation523>()).Select(v => new Station(v, this.World)).ToList();
+            Srms = Device.All.Where(v => v.HasProtocol<ISRM520>()).Select(v => new SRM(v, this.World)).ToList();
+            Bcrs = Device.All.Where(v => v.HasProtocol<IBCR81>()).Select(v => new BCR(v, this.World)).ToList();
+            Device91 = Device.All.Where(v => v.HasProtocol<IStation523>()).Select(v => new Device<IStation523>(v, this.World)).ToList();
+        }
+
+        protected override object Do(Tuple<string, string> tuple)
+        {
+            switch (tuple.Item1)
+            {
+                case "堆垛机":
+                    return Srms;
+
+                case "输送机":
+                    return Convs;
+
+                case "读码器":
+                    var b = Bcrs.FirstOrDefault(v => v.Entity.Code == tuple.Item2).Data.Content;
+                    var a = Bcrs.FirstOrDefault(v => v.Entity.Code == tuple.Item2).GetBCRCode();
+                    return Bcrs.FirstOrDefault(v => v.Entity.Code == tuple.Item2).GetBCRCode();
+
+                case "外检":
+                    return Device91;
+
+                default: return "未知设备类型";
+            }
+
+            //if (code.Contains("SRM")) return Device.All.Where(v => v.Code == code).Select(v => new SRM(v, this.World)).ToList();
+            //else if (code.Contains("BCR")) return Device.All.Where(v => v.Code == code).Select(v => new BCR(v, this.World)).ToList();
+            //else if (code.Contains("D91")) return Device.All.Where(v => v.Code == code).Select(v => new Device<IStation523>(v, this.World)).ToList();
+            //return Device.All.Where(v => v.Code == code).Select(v => new Station(v, this.World)).ToList();
+        }
+    }
+}

+ 111 - 0
成品库/WCS.WorkEngineering/Systems/NoInteractionSystems.cs

@@ -0,0 +1,111 @@
+using PlcSiemens.Core.Extension;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  无交互系统
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("无交互系统")]
+    public class NoInteractionSystems : DeviceSystem<Station>
+    {
+        public NoInteractionSystems()
+        {
+        }
+
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Station obj)
+        {
+            var key = $"WCS:Lock:无交互系统{obj.Entity.Code}";
+            try
+            {
+                if (RedisHub.Default.Get(key) != null)
+                {
+                    throw new KnownException($"[{obj.Entity.Code}]--触发并发管控", LogLevelEnum.High);
+                }
+                RedisHub.Default.Set(key, obj.Entity.Code);
+
+                #region 处理所有的新增任务
+
+                try
+                {
+                    List<WCS_TaskInfo> taskInfos = new List<WCS_TaskInfo>();
+                    SqlSugarHelper.Do(db =>
+                    {
+                        taskInfos = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.Status == Entity.TaskStatus.NewBuild).ToList();
+                    });
+                    if (taskInfos.Any())
+                    {
+                        foreach (var item in taskInfos)
+                        {
+                            try
+                            {
+                                SqlSugarHelper.Do(db =>
+                                {
+                                    var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item.ID).First() ?? throw new Exception($"未找到对应的WCS任务[{item.ID}]");
+                                    if (task.Type == TaskType.EnterDepot)
+                                    {
+                                        //更新任务状态
+                                        task.Status = Entity.TaskStatus.WaitingToExecute;
+                                        db.Default.Updateable(task).ExecuteCommand();
+                                        task.AddWCS_TASK_DTL(db, task.Device, $"初始化入库任务信息");
+                                    }
+                                    else if (task.Type == TaskType.OutDepot)
+                                    {
+                                        if (task.SrmStation.IsNullOrEmpty()) //如果没有指定放货站台
+                                        {
+                                            //获取堆垛机到目标地址的路径信息
+                                            var path = DevicePath.GetPath(task.Device, task.AddrTo);
+                                            task.SrmStation = path.Points[1].Code;
+                                        }
+                                        //更新任务状态
+                                        task.Status = Entity.TaskStatus.WaitingToExecute;
+                                        db.Default.Updateable(task).ExecuteCommand();
+                                        task.AddWCS_TASK_DTL(db, task.Device, $"初始化出库任务信息,放货站台:{task.SrmStation}");
+                                    }
+                                    else if (task.Type == TaskType.Delivery) //一楼叉车搬运任务
+                                    {
+                                    }
+                                    else if (task.Type == TaskType.EmptyInit)
+                                    {
+                                    }
+                                });
+                            }
+                            catch (Exception ex)
+                            {
+                                World.Log(ex.Message, LogLevelEnum.Mid);
+                                continue;
+                            }
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    World.Log(ex.Message, LogLevelEnum.Mid);
+                }
+
+                #endregion 处理所有的新增任务
+            }
+            finally
+            {
+                RedisHub.Default.Del(key);
+            }
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "2532";
+        }
+    }
+}

+ 44 - 0
成品库/WCS.WorkEngineering/Systems/RGVSystems.cs

@@ -0,0 +1,44 @@
+using ServiceCenter.Logs;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.RGV;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  Agv交互系统
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("RGV交互系统")]
+    public class RGVSystems : DeviceSystem<RGV>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public RGVSystems()
+        {
+        }
+
+        public override void Do(RGV obj)
+        {
+            //if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            //if (!obj.Data2.WorkMode.HasFlag(RGVWorkMode.Automatic)) return;
+            //if (!obj.Data2.SystemStatus.HasFlag(RGVSystemStatus.空闲)) return;
+            //if (obj.Data2.Status.HasFlag(RGVStatus.PH_Status)) throw new KnownException($"有光电", LogLevelEnum.High);
+            //obj.Data.TaskNumber = 12345;
+            //obj.Data.CmdType = RGVCmdType.PickPutGoods;
+            //obj.Data.StartPosition = 1663;
+            //obj.Data.DestPosition = 1672;
+            //obj.Data.VoucherNo++;
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.Code == "RGV1";
+            //return dev.HasFlag(Extensions.DeviceFlags.RGV);
+        }
+    }
+}

+ 60 - 0
成品库/WCS.WorkEngineering/Systems/SrmDebugSystem.cs

@@ -0,0 +1,60 @@
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.RGV;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  设备信息写入接口
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    public class SrmDebugSystem : ServiceSystem<SrmDebugInfo>
+    {
+        private List<SRM> Srms;
+
+        /// <summary>
+        ///  构造函数
+        /// </summary>
+        public SrmDebugSystem()
+        {
+            Srms = Device.All.Where(v => v.HasProtocol<ISRM520>()).Select(v => new SRM(v, this.World)).ToList();
+        }
+
+        protected override void Do(SrmDebugInfo info)
+        {
+            var srm = Srms.FirstOrDefault(v => v.Entity.Code == info.SrmCode);
+            srm.Data.TaskType = info.srmTaskType;
+            srm.Data.SLine = info.SLine;
+            srm.Data.SCol = info.SCol;
+            srm.Data.SLayer = info.SLayer;
+            srm.Data.ELine = info.ELine;
+            srm.Data.ECol = info.ECol;
+            srm.Data.ELayer = info.ELayer;
+            srm.Data.VoucherNo++;
+        }
+    }
+
+    /// <summary>
+    /// 设备写入信息
+    /// </summary>
+    public class SrmDebugInfo
+    {
+        public string SrmCode { get; set; }
+
+        public SrmTaskType srmTaskType { get; set; }
+
+        public short SLine { get; set; }
+
+        public short SCol { get; set; }
+
+        public short SLayer { get; set; }
+
+        public short ELine { get; set; }
+
+        public short ECol { get; set; }
+
+        public short ELayer { get; set; }
+    }
+}

+ 370 - 0
成品库/WCS.WorkEngineering/Systems/SrmSystems.cs

@@ -0,0 +1,370 @@
+using PlcSiemens.Core.Extension;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.WebApi.Controllers;
+using WCS.WorkEngineering.Worlds;
+using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
+using KnownException = ServiceCenter.Logs.KnownException;
+using TaskStatus = WCS.Entity.TaskStatus;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    /// 堆垛机系统
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("堆垛机系统")]
+    public class SrmSystems : DeviceSystem<SRM>
+    {
+        /// <summary>
+        /// 取货点设备集合
+        /// </summary>
+        private Dictionary<string, List<Station>> PickUpDevices = new Dictionary<string, List<Station>>();
+
+        /// <summary>
+        /// 放货设备
+        /// </summary>
+        private Dictionary<string, List<Station>> PutDevices = new Dictionary<string, List<Station>>();
+
+        public SrmSystems()
+        {
+            //获取所有的巷道集合
+            var devices = Device.All.Where(v => v.HasFlag(DeviceFlags.巷道));
+
+            //开始分配
+            foreach (var item in devices)
+            {
+                //取货设备
+                var srm = item.Targets.Where(v => v.HasFlag(DeviceFlags.堆垛机)).FirstOrDefault();
+                PickUpDevices.Add(srm.Code, item.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Station(v, this.World)).ToList());
+                //放货设备
+                srm = item.Sources.Where(v => v.HasFlag(DeviceFlags.堆垛机)).FirstOrDefault();
+                PutDevices.Add(srm.Code, item.Targets.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Station(v, this.World)).ToList());
+            }
+        }
+
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(SRM obj)
+        {
+            #region 处理完成任务
+
+            SqlSugarHelper.Do(db =>
+            {
+                var a = db.Default.Queryable<WCS_TaskInfo>().ToSql();
+                var c = db.Default.CurrentConnectionConfig.ConnectionString;
+                var b = db.Default.Queryable<WCS_TaskInfo>().ToList();
+            });
+
+            //判断DB520 完成任务确认清除信号 是否为1
+            if (obj.Data.OkAck == 1) throw new KnownException($"WCS任务完成确认信号[DB520.OkAck]未清除,请检查堆垛机处理异常原因", LogLevelEnum.Mid);
+
+            if (obj.Data2.TaskFinishiId > 0)
+            {
+                //处理完成的任务信息
+                WCS_TaskInfo taskInfo = null;
+                //开始处理
+                SqlSugarHelper.Do(db =>
+                {
+                    World.Log($"堆垛机任务处理:开始--完成任务{obj.Data2.TaskFinishiId}", LogLevelEnum.Low);
+
+                    #region 获取完成任务
+
+                    //根据DB521任务号获取对应任务
+                    var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskFinishiId);
+                    if (task == null) throw new KnownException($"堆垛机完成任务号{obj.Data2.TaskFinishiId},在WCS当前任务信息中未找到对应任务。", LogLevelEnum.High);
+                    if (task.Status != Entity.TaskStatus.StackerExecution) throw new KnownException($"任务{task.ID}状态是{task.Status.GetDescription()}.堆垛机完成任务需要对应任务状态处于堆垛机执行中", LogLevelEnum.High);
+
+                    #endregion 获取完成任务
+
+                    //根据任务类型做不同的处理
+                    switch (task.Type)
+                    {
+                        case TaskType.EnterDepot:
+                            //完成任务
+                            task.Status = Entity.TaskStatus.Finish;
+                            task.EedTime = DateTime.Now;
+                            db.Default.Updateable(task).ExecuteCommand();
+                            task.AddWCS_TASK_DTL(db, task.AddrTo, "入库任务结束");
+                            break;
+
+                        case TaskType.OutDepot:
+                            switch (task.OutType)
+                            {
+                                case OutTypeEnum.自动出库任务:
+                                    task.Status = Entity.TaskStatus.ConveyorExecution;
+                                    var dev = new Station(Device.All.FirstOrDefault(v => v.Code == task.SrmStation), this.World);
+                                    dev.Data.TaskNumber = task.ID;
+                                    db.Default.Updateable(task).ExecuteCommand();
+                                    task.AddWCS_TASK_DTL(db, task.SrmStation, "出库任务到达放货站台");
+                                    break;
+
+                                case OutTypeEnum.全自动手动出库任务:
+
+                                    break;
+
+                                case OutTypeEnum.半自动手动出库任务:
+                                    task.Status = Entity.TaskStatus.Finish;
+                                    task.EditTime = DateTime.Now;
+                                    db.Default.Updateable(task).ExecuteCommand();
+                                    task.AddWCS_TASK_DTL(db, task.SrmStation, "半自动手动出库任务结束");
+                                    break;
+
+                                default:
+                                    break;
+                            }
+
+                            break;
+
+                        case TaskType.TransferDepot:
+                            task.Status = Entity.TaskStatus.Finish;
+                            task.EedTime = DateTime.Now;
+                            db.Default.Updateable(task).ExecuteCommand();
+                            task.AddWCS_TASK_DTL(db, task.AddrTo, "移库任务结束");
+                            break;
+
+                        case TaskType.EmptyInit:
+                            task.Status = Entity.TaskStatus.Finish;
+                            task.EedTime = DateTime.Now;
+                            db.Default.Updateable(task).ExecuteCommand();
+                            task.AddWCS_TASK_DTL(db, task.AddrTo, "空轮初始化任务结束");
+                            break;
+                    }
+
+                    if (task.Status >= TaskStatus.Finish) task.CompleteOrCancelTasks(db);
+
+                    taskInfo = task;
+                });
+                if (taskInfo == null) throw new KnownException("数据库提交事务错误", LogLevelEnum.High);
+                // 写入信号
+                obj.Data.OkAck = 1;
+                //通知WMS任务完成
+                if (taskInfo.Status == TaskStatus.Finish) WmsApi.CompleteTask(taskInfo.ID);
+                if (taskInfo.Type == TaskType.OutDepot && taskInfo.Status == TaskStatus.ConveyorExecution) WmsApi.SrmPickOutCompleted(taskInfo.ID);
+
+                World.Log($"堆垛机任务处理:结束--完成任务{obj.Data2.TaskFinishiId}", LogLevelEnum.Mid);
+            }
+
+            #endregion 处理完成任务
+
+            //堆垛机是否可以下发任务
+            if (obj.Data2.VoucherNo != obj.Data.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid);
+            if (obj.Data2.AutoStatus != SrmAutoStatus.Automatic) throw new KnownException($"堆垛机处于{obj.Data2.AutoStatus.GetDescription()}模式", LogLevelEnum.Low);
+            if (obj.Data2.RunStatus != SrmRunStatus.Idle) throw new KnownException($"堆垛机处于{obj.Data2.RunStatus.GetDescription()}状态", LogLevelEnum.High);
+
+            //默认没有移库任务
+            bool isTransfer = false;
+
+            //出入库优先级任务 1:无优先 2:入库 3:出库
+            int enterOrOut = 1;
+
+            //再检查是否有等待执行的货物
+            SqlSugarHelper.Do(db =>
+            {
+                //获取当前堆垛机的所有未完成任务
+                var tasks = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Status < Entity.TaskStatus.Finish && (v.Device == obj.Entity.Code));
+                //任务集合是否有处于堆垛机执行状态的任务
+                if (tasks.Any(v => v.Status == Entity.TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High);
+
+                //不存在调整优先级任务,判断是否存在移库任务
+                isTransfer = tasks.Any(v => v.Type == TaskType.TransferDepot && v.Status == Entity.TaskStatus.NewBuild);
+                //}
+                if (!isTransfer) //存在调整优先级任务
+                {
+                    //获取出库任务中新建状态最大优先级
+                    var outPriorityNewBuild = tasks.Where(v => v.Type == TaskType.OutDepot && v.Status == Entity.TaskStatus.WaitingToExecute).Max(v => v.Priority);
+                    //获取入库任务中最大优先级
+                    var enterPriority = tasks.Where(v => v.Type == TaskType.EnterDepot && v.Status < Entity.TaskStatus.StackerExecution).Max(v => v.Priority);
+                    //出入库最大优先级相加大于零
+                    if (outPriorityNewBuild + enterPriority > 0)
+                    {
+                        //出入库优先级任务 1:无优先 2:入库 3:出库
+                        enterOrOut = enterPriority > outPriorityNewBuild ? 2 : 3;
+                    }
+                }
+            });
+
+            #region 移库
+
+            if (isTransfer)
+            {
+                WCS_TaskInfo taskInfo = null;
+                SqlSugarHelper.Do(db =>
+                   {
+                       //获取一条当前堆垛机优先级最高的新建移库任务
+                       var task = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Device == obj.Entity.Code && v.Type == TaskType.TransferDepot && v.Status == Entity.TaskStatus.NewBuild)
+                                                                      .OrderByDescending(v => v.Priority)
+                                                                      .First() ?? throw new KnownException("未找到移库任务", LogLevelEnum.High);
+                       //任务状态改为堆垛机执行中
+                       task.Status = Entity.TaskStatus.StackerExecution;
+                       task.StartTime = DateTime.Now;
+                       db.Default.Updateable(task).ExecuteCommand();
+                       task.AddWCS_TASK_DTL(db, task.AddrFrom, task.Device, $"堆垛机{obj.Entity.Code}开始执行任务");
+                       taskInfo = task;
+                   });
+                if (taskInfo == null) throw new KnownException("数据更新错误", LogLevelEnum.High);
+                var addrFrom = taskInfo.AddrFrom.Split("-");
+                var addrTo = taskInfo.AddrTo.Split("-");
+                World.Log($"堆垛机任务处理:开始--下发移库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid);
+                //下发任务
+                obj.Data.TaskNumber = taskInfo.ID;
+                obj.Data.SLine = addrFrom[0].ToShort();
+                obj.Data.SCol = addrFrom[1].ToShort();
+                obj.Data.SLayer = addrFrom[2].ToShort();
+                obj.Data.ELine = addrTo[0].ToShort();
+                obj.Data.ECol = addrTo[1].ToShort();
+                obj.Data.ELayer = addrTo[2].ToShort();
+                obj.Data.TaskType = SrmTaskType.MoveGoods;
+                obj.Data.VoucherNo++;
+                World.Log($"堆垛机任务处理:结束---下发移库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid);
+            }
+
+            #endregion 移库
+
+            #region 出入库
+
+            //上一个周期是不是出库任务 第一次获取返回结果会是false
+            var lastIsOut = obj.Entity.GetFlag<bool>("LastIsOut");
+            obj.Entity.SetFlag("LastIsOut", !lastIsOut);
+
+            //入库任务优先 或 上一个周期是出库任务并且出库任务无优先
+            if (enterOrOut == 2 || (lastIsOut && enterOrOut == 1)) //入库任务
+            {
+                //判断本次优先执行楼层,并设置下次执行时优先楼层
+                var floor = obj.Entity.GetFlag<int>("FloorIn");
+                floor = floor % 2 + 1;
+                obj.Entity.SetFlag("FloorIn", floor);
+
+                //获取当前堆垛机所有的取货站台
+                var arrIn = PickUpDevices.First(v => v.Key == obj.Entity.Code).Value;
+                if (!arrIn.Any()) throw new KnownException($"堆垛机{obj.Entity.Code}无取货路径点", LogLevelEnum.High);
+
+                //获取有货的设备
+                arrIn = arrIn.Where(v => v.Data.TaskNumber > 0 && v.Data3.Status.HasFlag(StationStatus.PH_Status) && !v.Data3.Status.HasFlag(StationStatus.Run)).ToList();
+                if (!arrIn.Any()) throw new KnownException($"[{obj.Entity.Code}]等待入库任务输送到位", LogLevelEnum.Mid);
+                WCS_TaskInfo taskInfo = null;
+                Station station = null;
+                SqlSugarHelper.Do(db =>
+                {
+                    //根据有货设备的任务号获取所有类型为入库状态为输送机执行中的任务
+                    var tasks = db.Default.Queryable<WCS_TaskInfo>().Where(v => (v.Type == TaskType.EnterDepot || v.Type == TaskType.EmptyInit)
+                                                                              && v.Status == TaskStatus.ConveyorExecution
+                                                                              && arrIn.Select(p => p.Data.TaskNumber).Contains(v.ID));
+                    //按条件先后排序获取一条排序后第一条结果1.优先级2.所在楼层与本次优先执行楼层 TODO:待验证排序结果
+                    var task = tasks.OrderByDescending(v => v.Priority).OrderByDescending(v => v.Floor == floor ? 1 : 0).First() ?? throw new KnownException($"{obj.Entity.Code}未找到入库任务", LogLevelEnum.High);
+
+                    //获取任务所有设备
+                    station = arrIn.First(v => v.Data.TaskNumber == task.ID);
+                    //获取当前货物巷道
+                    var res = WmsApi.GetLocalIn(task.ID, task.Device, station.Entity.Code, task.Height);
+                    var loc = res.ResData.CellNo.Split("-");
+                    task.Status = TaskStatus.StackerExecution;
+                    task.AddrTo = $"{loc[0]}-{loc[1]}-{loc[2]}";
+                    task.LastInteractionPoint = station.Entity.Code;
+                    task.EditWho = "WCS";
+                    db.Default.Updateable(task).ExecuteCommand();
+                    task.AddWCS_TASK_DTL(db, station.Entity.Code, task.AddrTo, "任务下发堆垛机执行");
+
+                    taskInfo = task;
+                });
+
+                if (taskInfo == null) throw new KnownException("数据更新错误", LogLevelEnum.High);
+                var addrTo = taskInfo.AddrTo.Split("-");
+                World.Log($"堆垛机任务处理:开始--下发入库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid);
+                //下发任务
+                obj.Data.TaskNumber = taskInfo.ID;
+                obj.Data.TaskType = SrmTaskType.Default;
+                obj.Data.SLine = station.Entity.Code.ToShort();
+                obj.Data.SCol = 0;
+                obj.Data.SLayer = 0;
+                obj.Data.ELine = addrTo[0].ToShort();
+                obj.Data.ECol = addrTo[1].ToShort();
+
+                obj.Data.ELayer = addrTo[2].ToShort();
+                obj.Data.VoucherNo++;
+                World.Log($"堆垛机任务处理:结束---下发入库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid);
+            }
+            else if (enterOrOut == 3 || !lastIsOut) //出库任务
+            {
+                //判断本次优先执行楼层,并设置下次执行时优先楼层
+
+                var floor = obj.Entity.GetFlag<int>("FloorOut");
+
+                floor = floor % 2 + 1;
+                obj.Entity.SetFlag("FloorOut", floor);
+
+                //获取当前堆垛机所有的取货站台
+                var arrOut = PutDevices.First(v => v.Key == obj.Entity.Code).Value;
+
+                if (!arrOut.Any()) throw new KnownException($"堆垛机{obj.Entity.Code}无放货路径点", LogLevelEnum.High);
+
+                //获取可以放货的设备集合
+                arrOut = arrOut.Where(v => !v.Data3.Status.HasFlag(StationStatus.PH_Status) //无光电
+                                                && !v.Data3.Status.HasFlag(StationStatus.Run) //未运行
+                                                && !v.Data3.Status.HasFlag(StationStatus.OT_Status) //无任务
+                                                && !v.Data3.Status.HasFlag(StationStatus.UnassignedTask) //未分配任务
+                                                && v.Data3.Status.HasFlag(StationStatus.Auto)).ToList(); //自动
+
+                if (!arrOut.Any()) throw new KnownException($"[{obj.Entity.Code}]等待出库任务输送到位", LogLevelEnum.Mid);
+
+                WCS_TaskInfo taskInfo = null;
+
+                SqlSugarHelper.Do(db =>
+               {
+                   var allOutCode = arrOut.Select(v => v.Entity.Code).ToList();
+
+                   //按条件先后排序获取一条排序后第一条结果1.优先级2.所在楼层与本次优先执行楼层
+                   var task = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Type == TaskType.OutDepot && v.Status == TaskStatus.WaitingToExecute)
+                                                                  .Where(v => allOutCode.Contains(v.SrmStation))
+                                                                  .OrderByDescending(v => v.Priority)
+                                                                  .OrderByDescending(v => v.Floor == floor ? 1 : 0)
+                                                                  .OrderBy(v => v.AddTime)
+                                                                  .First();
+                   if (task == null) throw new KnownException($"{obj.Entity.Code}未找到出库任务", LogLevelEnum.High);
+                   var taskId = task.ID;
+                   task.Status = TaskStatus.StackerExecution;
+                   task.LastInteractionPoint = task.Device;
+                   task.EditWho = "WCS";
+                   db.Default.Updateable(task).ExecuteCommand();
+                   task.AddWCS_TASK_DTL(db, task.Device, task.SrmStation, "任务下发堆垛机执行");
+                   taskInfo = task;
+               });
+
+                if (taskInfo == null) throw new KnownException("数据更新错误", LogLevelEnum.High);
+
+                var addrFrom = taskInfo.AddrFrom.Split("-");
+                World.Log($"堆垛机任务处理:开始--下发出库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid);
+                obj.Data.TaskNumber = taskInfo.ID;
+                obj.Data.SLine = addrFrom[0].ToShort();
+                obj.Data.SCol = addrFrom[1].ToShort();
+                obj.Data.SLayer = addrFrom[2].ToShort();
+                obj.Data.ELine = taskInfo.SrmStation.ToShort();
+                obj.Data.ECol = 0;
+                obj.Data.ELayer = 0;
+                obj.Data.TaskType = SrmTaskType.Default;
+                obj.Data.VoucherNo++;
+                World.Log($"堆垛机任务处理:结束---下发出库任务[{obj.Data.TaskNumber}][{obj.Data.SLine}][{obj.Data.SCol}][{obj.Data.SLayer}][{obj.Data.ELine}][{obj.Data.ECol}][{obj.Data.ELayer}][{obj.Data.TaskType}][{obj.Data.VoucherNo}]", LogLevelEnum.Mid);
+            }
+
+            #endregion 出入库
+        }
+
+        public override bool Select(Device dev)
+        {
+            if (dev.Code is "SRM1" or "SRM2")
+            {
+                var a = 1;
+            }
+            return dev.HasProtocol(typeof(ISRM520));
+        }
+    }
+}

+ 118 - 0
成品库/WCS.WorkEngineering/Systems/一楼叠盘机入库.cs

@@ -0,0 +1,118 @@
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.WebApi.Controllers;
+using WCS.WorkEngineering.WebApi.Models.WMS.Request;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  一楼叠盘机入库
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("一楼叠盘机入库")]
+    public class 一楼叠盘机入库 : DeviceSystem<Device<IStation520, IStation521, IStation523>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Device<IStation520, IStation521, IStation523> obj)
+        {
+            obj.入库站点是否被禁止();
+            obj.入库站点是否满足执行条件();
+
+            WCS_TaskInfo task = null;//处理完成的任务
+            try
+            {
+                var device = "";
+                var barcode = "";
+
+                switch (obj.Entity.Code)
+                {
+                    case "2527":
+                        device = "SRM1";
+                        barcode = "TPA";
+                        break;
+
+                    case "2528":
+                        device = "SRM1";
+                        barcode = "TPA";
+                        break;
+
+                    case "2727":
+                        device = "SRM2";
+                        barcode = "TPA";
+                        break;
+
+                    case "2728":
+                        device = "SRM2";
+                        barcode = "TPA";
+                        break;
+                };
+
+                SqlSugarHelper.Do(_db =>
+                {
+                    var db = _db.Default;
+
+                    //验证是否有对应的任务
+                    if (!db.Queryable<WCS_TaskInfo>().Any(v => v.BarCode == barcode))
+                    {
+                        var res = WmsApi.OneFloorWorkerBuildEmptyPalletsStock(new OneFloorWorkerBuildEmptyPalletsStockRequest()
+                        {
+                            PalletCode = barcode,
+                            StartLoc = obj.Entity.Code,
+                            Height = 2
+                        });
+                        if (res.ResCode == WebApi.Models.WMS.Response.ResponseStatusCodeEnum.Sucess) return;
+                    }
+                    //找到对应的任务
+                    var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.BarCode == barcode);
+                    if (taskInfo.Status == Entity.TaskStatus.WaitingToExecute)
+                    {
+                        var tunnel = obj.Entity.Targets.Where(v => v.HasFlag(Extensions.DeviceFlags.巷道)).FirstOrDefault();
+                        //开始对任务进行处理
+                        taskInfo.Status = Entity.TaskStatus.ConveyorExecution;
+                        taskInfo.StartTime = DateTime.Now;
+                        taskInfo.SrmStation = taskInfo.AddrFrom;
+                        taskInfo.LastInteractionPoint = obj.Entity.Code;
+                        taskInfo.Tunnel = tunnel.Code;
+                        taskInfo.Height = 2;
+                        switch (obj.Entity.Code)
+                        {
+                            case "2527": taskInfo.Device = "SRM1"; break;
+                            case "2727": taskInfo.Device = "SRM2"; break;
+                            case "2528": taskInfo.Device = "SRM1"; break;
+                            case "2728": taskInfo.Device = "SRM2"; break;
+                        };
+                        taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, "开始执行入库任务");
+                        db.Updateable(taskInfo).ExecuteCommand();
+                        taskInfo.updateRedisHash();
+                        task = taskInfo;
+                    }
+                    else return;
+                });
+            }
+            catch (Exception ex)
+            {
+                throw new KnownException(ex.Message, LogLevelEnum.High);
+            }
+            if (task == null) return;
+
+            World.Log($"任务处理:开始-DB520[{obj.Data.TaskNumber}]-[{obj.Data.VoucherNo}]-DB521[{obj.Data2.TaskNumber}]-[{obj.Data2.VoucherNo}]");
+            obj.Data.TaskNumber = task.ID;
+            obj.Data.VoucherNo++;
+            World.Log($"任务处理:结束-DB520[{obj.Data.TaskNumber}]-[{obj.Data.VoucherNo}]-DB521[{obj.Data2.TaskNumber}]-[{obj.Data2.VoucherNo}]");
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(Extensions.DeviceFlags.一楼叠盘机);
+        }
+    }
+}

+ 98 - 0
成品库/WCS.WorkEngineering/Systems/一楼扫码入库.cs

@@ -0,0 +1,98 @@
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.WebApi.Controllers;
+using WCS.WorkEngineering.WebApi.Models.WMS.Request;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  一楼入库工位处理系统
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("一楼扫码入库")]
+    public class 一楼扫码入库 : DeviceSystem<Device<IStation520, IStation521, IStation523, IStation91, IBCR81>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public 一楼扫码入库()
+        {
+        }
+
+        public override void Do(Device<IStation520, IStation521, IStation523, IStation91, IBCR81> obj)
+        {
+            obj.入库站点是否被禁止();
+            obj.入库站点是否满足执行条件();
+
+            WCS_TaskInfo task = null;//处理完成的任务
+            try
+            {
+                SqlSugarHelper.Do(_db =>
+                {
+                    var db = _db.Default;
+                    //获取托盘条码
+                    var barcode = obj.Data5.GetBCRCode();
+                    //var barcode = "TAP00001";
+                    //验证是否有对应的任务
+                    if (!db.Queryable<WCS_TaskInfo>().Any(v => v.BarCode == barcode))
+                    {
+                        var res = WmsApi.OneFloorWorkerBuildEmptyPalletsStock(new OneFloorWorkerBuildEmptyPalletsStockRequest()
+                        {
+                            PalletCode = barcode,
+                            StartLoc = obj.Entity.Code,
+                            Height = 1
+                        });
+                        if (res.ResCode == WebApi.Models.WMS.Response.ResponseStatusCodeEnum.Sucess) return;
+                    }
+                    //找到对应的任务
+                    var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.BarCode == barcode);
+                    if (taskInfo.Status == Entity.TaskStatus.WaitingToExecute)
+                    {
+                        var tunnel = obj.Entity.Targets.Where(v => v.HasFlag(Extensions.DeviceFlags.巷道)).FirstOrDefault();
+                        //开始对任务进行处理
+                        taskInfo.Status = Entity.TaskStatus.ConveyorExecution;
+                        taskInfo.StartTime = DateTime.Now;
+                        taskInfo.SrmStation = taskInfo.AddrFrom;
+                        taskInfo.LastInteractionPoint = obj.Entity.Code;
+                        taskInfo.Tunnel = tunnel.Code;
+                        taskInfo.Height = 1;
+                        switch (obj.Entity.Code)
+                        {
+                            case "2532": taskInfo.Device = "SRM1"; break;
+                            case "2732": taskInfo.Device = "SRM2"; break;
+                        };
+                        taskInfo.AddWCS_TASK_DTL(_db, obj.Entity.Code, "开始执行入库任务");
+                        db.Updateable(taskInfo).ExecuteCommand();
+                        taskInfo.updateRedisHash();
+                        task = taskInfo;
+                    }
+                    else return;
+                });
+            }
+            catch (Exception ex)
+            {
+                throw new KnownException(ex.Message, LogLevelEnum.High);
+            }
+            if (task == null) return;
+
+            World.Log($"任务处理:开始-DB520[{obj.Data.TaskNumber}]-[{obj.Data.VoucherNo}]-DB521[{obj.Data2.TaskNumber}]-[{obj.Data2.VoucherNo}]-[{obj.Data2.Request}]");
+            obj.Data.TaskNumber = task.ID;
+            obj.Data.VoucherNo++;
+            World.Log($"任务处理:结束-DB520[{obj.Data.TaskNumber}]-[{obj.Data.VoucherNo}]-DB521[{obj.Data2.TaskNumber}]-[{obj.Data2.VoucherNo}]");
+        }
+
+        public override bool Select(Device dev)
+        {
+            //return dev.Code == "2532";
+            return dev.HasFlag(Extensions.DeviceFlags.一楼扫码);
+        }
+    }
+}

+ 120 - 0
成品库/WCS.WorkEngineering/Systems/主线分流点.cs

@@ -0,0 +1,120 @@
+using Newtonsoft.Json;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  主线分流
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("主线分流点")]
+    public class 主线分流点 : DeviceSystem<Device<IStation520, IStation521, IStation523, IBCR83>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Device<IStation520, IStation521, IStation523, IBCR83> obj)
+        {
+            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            if (obj.Data4.index == obj.Data4.Lastindex) throw new KnownException("扫码结果未更新", LogLevelEnum.Mid);
+            if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+
+            //获取条码
+            var bcr = obj.Data4.BcrCode.Trim('\0').Trim();
+            if (string.IsNullOrWhiteSpace(bcr))
+            {
+                obj.Data.TaskNumber = 1;
+                obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+                obj.Data.GoodsEnd = 418;
+                obj.Data.VoucherNo++;
+                World.Log($"执行记录:条码:[{bcr}];任务号[{1}],扫码错误");
+            }
+            try
+            {
+                var key = $"AllocationWarehouseSort:{bcr}";
+                var value = RedisHub.WMS.Get(key);
+                if (value == null)
+                {
+                    obj.Data.TaskNumber = 1;
+                    obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+                    obj.Data.GoodsEnd = 418;
+                    obj.Data.VoucherNo++;
+                }
+                //throw new KnownException($"{bcr}无入库信息", LogLevelEnum.Low);
+
+                //获取到仓库Id
+                var mainlineDiversion = JsonConvert.DeserializeObject<MainlineDiversion>(value);
+                //更具仓库ID来分配目标地址
+                //TODO:暂未考虑工字轮型号,统一往09走问题
+                int nextAdd = 0;
+                switch (mainlineDiversion.WarehouseCode)
+                {
+                    case "1N":
+                        nextAdd = 418;
+                        break;
+
+                    case "1S":
+                        nextAdd = 0;
+                        break;
+
+                    case "2N":
+                        nextAdd = 0;
+                        break;
+
+                    case "2S":
+                        nextAdd = 0;
+                        break;
+
+                    case "3N":
+                        nextAdd = 0;
+                        break;
+
+                    case "3S":
+                        nextAdd = 0;
+                        break;
+                }
+
+                obj.Data.TaskNumber = mainlineDiversion.TaskId;
+                obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+                obj.Data.GoodsEnd = nextAdd.ToShort();
+                obj.Data.VoucherNo++;
+                World.Log($"执行记录:条码:[{bcr}];任务号[{mainlineDiversion.TaskId}]");
+                RedisHub.WMS.Del(key);
+            }
+            catch (Exception e)
+            {
+                var a = 0;
+            }
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(Extensions.DeviceFlags.主线分流点);
+        }
+    }
+
+    /// <summary>
+    ///  主线分流
+    /// </summary>
+    public class MainlineDiversion
+    {
+        /// <summary>
+        ///  任务号
+        /// </summary>
+        public int TaskId { get; set; }
+
+        /// <summary>
+        ///  仓库号
+        /// </summary>
+        public string WarehouseCode { get; set; }
+    }
+}

+ 52 - 0
成品库/WCS.WorkEngineering/Systems/桁架.cs

@@ -0,0 +1,52 @@
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Protocol.Truss;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  桁架
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("桁架")]
+    public class 桁架 : DeviceSystem<Truss>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Truss obj)
+        {
+            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            if (obj.Data2.Status != TrussStatus.Idle) return;
+            var devs = Device.All.Where(x => x.Code is "475" or "476" or "477" or "478" or "479").Select(x => new Device<IStation524>(x, World)).OrderBy(x => x.Entity.Code).ToArray();
+
+            //var devs1 = Device.All.Where(x => x.Code is "475" or "476" or "477" or "478" or "479").Select(x => new Device<IStation523>(x, World)).ToList();
+
+            obj.Data.DestPosition_1 = 19;
+            obj.Data.TargetPallte1 = 10;
+            obj.Data.Task1_1 = devs[0].Data.TaskNumber;
+            obj.Data.Dest1_1 = 1;
+            obj.Data.Task1_2 = devs[1].Data.TaskNumber; ;
+            obj.Data.Dest1_2 = 2;
+            obj.Data.Task1_3 = devs[2].Data.TaskNumber; ;
+            obj.Data.Dest1_3 = 3;
+            obj.Data.Task1_4 = devs[3].Data.TaskNumber; ;
+            obj.Data.Dest1_4 = 4;
+            obj.Data.Task1_5 = devs[4].Data.TaskNumber; ;
+            obj.Data.Dest1_5 = 5;
+            obj.Data.TaskSum1 = devs.Length.ToShort();
+            obj.Data.VoucherNo++;
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(Extensions.DeviceFlags.桁架);
+        }
+    }
+}

+ 49 - 0
成品库/WCS.WorkEngineering/Systems/桁架分流点.cs

@@ -0,0 +1,49 @@
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Worlds;
+using WCS.WorkEngineering.Extensions;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  桁架分流点
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("桁架分流点")]
+    public class 桁架分流点 : DeviceSystem<Device<IStation520, IStation521, IStation523>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Device<IStation520, IStation521, IStation523> obj)
+        {
+            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+
+            SqlSugarHelper.Do(_db =>
+            {
+                var db = _db.Default;
+                var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber) ?? throw new KnownException("未找到对应的WCS任务", LogLevelEnum.Mid);
+            });
+
+            obj.Data.TaskNumber = obj.Data2.TaskNumber;
+            obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+            obj.Data.GoodsEnd = 475;
+            obj.Data.VoucherNo++;
+            World.Log($"执行记录:任务号[{obj.Data2.TaskNumber}][{obj.Data.VoucherNo}]");
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(Extensions.DeviceFlags.桁架分流点);
+        }
+    }
+}

+ 47 - 0
成品库/WCS.WorkEngineering/Systems/桁架缓存放行点.cs

@@ -0,0 +1,47 @@
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    [BelongTo(typeof(MainWorld))]
+    [Description("桁架缓存放行点")]
+    public class 桁架缓存放行点 : DeviceSystem<Device<IStation520, IStation521, IStation523>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Device<IStation520, IStation521, IStation523> obj)
+        {
+            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (obj.Data3.Status.HasFlag(StationStatus.PH_Status) && obj.Data2.Request == 0) throw new KnownException("有光电无请求", LogLevelEnum.Mid);
+            if (!obj.Data3.Status.HasFlag(StationStatus.PH_Status) && obj.Data2.Request == 1) throw new KnownException("无光电有请求", LogLevelEnum.Mid);
+            if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (!obj.Data3.Status.HasFlag(StationStatus.PH_Status)) throw new KnownException("无光电", LogLevelEnum.Mid);
+            if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+
+            SqlSugarHelper.Do(_db =>
+            {
+                var db = _db.Default;
+                var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber) ?? throw new KnownException("未找到对应的WCS任务", LogLevelEnum.Mid);
+            });
+
+            obj.Data.TaskNumber = obj.Data2.TaskNumber;
+            obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+            obj.Data.GoodsEnd = 455;
+            obj.Data.VoucherNo++;
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(Extensions.DeviceFlags.桁架缓存放行点);
+        }
+    }
+}

+ 37 - 0
成品库/WCS.WorkEngineering/Systems/湿拉满轮帘线芯股第一次扫码.cs

@@ -0,0 +1,37 @@
+using Newtonsoft.Json;
+using ServiceCenter.Redis;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.BCR;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.WebApi.Controllers;
+using WCS.WorkEngineering.Worlds;
+using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  湿拉满轮帘线芯股第一次扫码
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("湿拉满轮帘线芯股第一次扫码")]
+    public class 湿拉满轮帘线芯股第一次扫码 : DeviceSystem<Device<IStation520, IStation521, IStation523, IBCR83>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Device<IStation520, IStation521, IStation523, IBCR83> obj)
+        {
+            var bcrCodeList = obj.Data4.GetBcrCodeList();
+            //获取当前站台对应的编码信息
+            WmsApi.EnteMainLine(bcrCodeList, obj.Entity.Code);
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(DeviceFlags.满轮主线第一次扫码);
+        }
+    }
+}

+ 58 - 0
成品库/WCS.WorkEngineering/Systems/环形库分流点.cs

@@ -0,0 +1,58 @@
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.SqlSugars;
+using System.ComponentModel;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Worlds;
+
+namespace WCS.WorkEngineering.Systems
+{
+    /// <summary>
+    ///  分流点
+    /// </summary>
+    [BelongTo(typeof(MainWorld))]
+    [Description("环形库分流点")]
+    public class 环形库分流点 : DeviceSystem<Device<IStation520, IStation521, IStation523, IStation91>>
+    {
+        protected override bool ParallelDo => true;
+
+        protected override bool SaveLogsToFile => true;
+
+        public override void Do(Device<IStation520, IStation521, IStation523, IStation91> obj)
+        {
+            if (obj.Data.VoucherNo != obj.Data2.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo}-DB521:{obj.Data2.VoucherNo}", LogLevelEnum.High);
+            if (obj.Data3.Status.HasFlag(StationStatus.Run)) throw new KnownException("设备运行中", LogLevelEnum.Low);
+            if (!obj.Data3.Status.HasFlag(StationStatus.OT_Status)) throw new KnownException("站台货物信息与实际占用不一致", LogLevelEnum.Low);
+            if (obj.Data2.Request != 1) throw new KnownException("无请求", LogLevelEnum.Mid);
+
+            if (obj.Data2.TaskNumber == 1)
+            {
+                obj.Data.TaskNumber = 591;
+                obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+                obj.Data.GoodsEnd = 591;
+                obj.Data.VoucherNo++;
+                World.Log($"执行记录:任务号[{591}]");
+            }
+
+            SqlSugarHelper.Do(_db =>
+            {
+                var db = _db.Default;
+                var taskInfo = db.Queryable<WCS_TaskInfo>().First(v => v.ID == obj.Data2.TaskNumber) ?? throw new KnownException("未找到对应的WCS任务", LogLevelEnum.Mid);
+            });
+
+            obj.Data.TaskNumber = obj.Data2.TaskNumber;
+            obj.Data.GoodsStart = obj.Entity.Code.ToShort();
+            obj.Data.GoodsEnd = 455;
+            obj.Data.VoucherNo++;
+            World.Log($"执行记录:任务号[{obj.Data2.TaskNumber}]");
+        }
+
+        public override bool Select(Device dev)
+        {
+            return dev.HasFlag(Extensions.DeviceFlags.环形库分流点);
+        }
+    }
+}

+ 28 - 0
成品库/WCS.WorkEngineering/WCS.WorkEngineering.csproj

@@ -0,0 +1,28 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net7.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+    <NoWarn>1701;1702;8602;8616;8618;8625;8600;8603;8714;1591</NoWarn>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <NoWarn>1701;1702;8602;8616;8618;8625;8600;8603;8714;1591</NoWarn>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Remove="Systems\puiaxxwa.5zv~" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MessagePack" Version="2.5.108" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.5" />
+    <PackageReference Include="ServiceCenter" Version="1.0.5" />
+  </ItemGroup>
+
+</Project>

+ 238 - 0
成品库/WCS.WorkEngineering/WebApi/Controllers/AgvApi.cs

@@ -0,0 +1,238 @@
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.WebApi;
+using WCS.WorkEngineering.WebApi.Models.AGV;
+using WCS.WorkEngineering.WebApi.Models.AGV.Request;
+using WCS.WorkEngineering.WebApi.Models.AGV.Response;
+using WCS.WorkEngineering.WebApi.Models.WCS.Response;
+using WCS.WorkEngineering.WebApi.Models.WMS.Request;
+using WCS.WorkEngineering.WebApi.Models.WMS.Response;
+
+namespace WCS.WorkEngineering.WebApi.Controllers
+{
+    /// <summary>
+    ///  AGV接口
+    /// </summary>
+    public static class AgvApi
+    {
+        private static string _AgvUrl = null!;
+
+        /// <summary>
+        /// AGV地址
+        /// </summary>
+        public static string AgvUrl
+        {
+            get
+            {
+                _AgvUrl ??= RedisHub.Default.Check("AgvUrl");
+                if (string.IsNullOrEmpty(_AgvUrl))
+                {
+                    throw new KnownException($"请在Redis配置AgvUrl", LogLevelEnum.High);
+                }
+                return _AgvUrl;
+            }
+        }
+
+        #region 任务单生成
+
+        /// <summary>
+        ///  满轮入库
+        /// </summary>
+        /// <param name="ctnrCode">RFID</param>
+        /// <param name="position">取货机台</param>
+        /// <param name="taskCode">WMS任务号</param>
+        /// <param name="priority">优先级</param>
+        /// <returns></returns>
+        public static GenAgvSchedulingTaskResponse 满轮入库(string ctnrCode, string position, string taskCode, string priority)
+        {
+            return GenAgvSchedulingTask("iwms_third", ctnrCode, "4", new List<positionCodeClass>()
+            {
+                new positionCodeClass(){ //取货机台
+                    positionCode=position,
+                    type="00"
+                },
+                new positionCodeClass(){ //巷道分配点
+                    positionCode="HJLK",
+                    type="00"
+                },
+                new positionCodeClass(){ //预分配放货点
+                    positionCode="1015",
+                    type="00"
+                }
+            }, priority, taskCode, "ZTGT03", "1");
+        }
+
+        /// <summary>
+        ///  机台补空
+        /// </summary>
+        /// <param name="position">补空机台</param>
+        /// <param name="taskCode">WMS任务号</param>
+        /// <param name="priority">优先级</param>
+        /// <returns></returns>
+        public static GenAgvSchedulingTaskResponse 机台补空(string position, string taskCode, string priority)
+        {
+            return GenAgvSchedulingTask("iWMS", "", "4", new List<positionCodeClass>()
+            {
+                new positionCodeClass(){ //合金库空区域
+                    positionCode="21",
+                    type="04"
+                },
+                new positionCodeClass(){ //目标机台
+                    positionCode=position,
+                    type="00"
+                }
+            }, priority, taskCode, "ZTGT03", "0");
+        }
+
+        /// <summary>
+        ///  缓存架补空
+        /// </summary>
+        /// <param name="taskCode">任务号</param>
+        /// <param name="nextPositionCode">取货地址</param>
+        /// <returns></returns>
+        public static ContinueTaskResponse 缓存架补空(string taskCode, string nextPositionCode)
+        {
+            return ContinueTask(taskCode, nextPositionCode);
+        }
+
+        /// <summary>
+        ///  机台补满
+        /// </summary>
+        /// <param name="ctnrCode">RFID</param>
+        /// <param name="position1">取货站台</param>
+        /// <param name="position2">放货机台</param>
+        /// <param name="taskCode">WMS任务号</param>
+        /// <param name="priority">优先级</param>
+        /// <returns></returns>
+        public static GenAgvSchedulingTaskResponse 机台补满(string ctnrCode, string position1, string position2, string taskCode, string priority)
+        {
+            return GenAgvSchedulingTask("iWMS", ctnrCode, "1", new List<positionCodeClass>()
+            {
+                new positionCodeClass(){ //取货站台
+                    positionCode=position1,
+                    type="00"
+                },
+                new positionCodeClass(){ //放货机台
+                    positionCode=position2,
+                    type="00"
+                }
+            }, priority, taskCode, "ZTGT21", "-1");
+        }
+
+        /// <summary>
+        ///  Agv任务单生成接口
+        /// </summary>
+        /// <param name="clienCode">客户端编号</param>
+        /// <param name="ctnrCode">容器编号</param>
+        /// <param name="ctnrTyp">容器类型</param>
+        /// <param name="positionCodePath">路径</param>
+        /// <param name="priority">优先级</param>
+        /// <param name="taskCode">任务单号</param>
+        /// <param name="taskType">任务类型</param>
+        /// <param name="hjTaskTy">合金任务模板</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static GenAgvSchedulingTaskResponse GenAgvSchedulingTask(string clienCode, string ctnrCode, string ctnrTyp, List<positionCodeClass> positionCodePath, string priority, string taskCode, string taskType, string hjTaskTy)
+        {
+            var res = APICaller.CallApi2<GenAgvSchedulingTaskResponse>(AgvUrl + "/rcms/services/rest/hikRpcService/genAgvSchedulingTask", new GenAgvSchedulingTaskRequest
+            {
+                clientCode = clienCode,
+                ctnrCode = ctnrCode,
+                ctnrTyp = ctnrTyp,
+                interfaceName = "genAgvSchedulingTask",
+                positionCodePath = positionCodePath,
+                priority = priority,
+                reqCode = Guid.NewGuid().ToString().Replace("-", ""),
+                taskCode = taskCode,
+                taskTyp = taskType,
+                hjTaskTy = hjTaskTy,
+                tokenCode = "56898661ea976b748f328cefa6960434",
+            });
+            if (res.code != AgvResponseCode.Success)
+            {
+                throw new KnownException(res.message, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        #endregion 任务单生成
+
+        #region 继续执行任务
+
+        /// <summary>
+        ///  继续执行任务
+        /// </summary>
+        /// <param name="taskCode">AGV任务号</param>
+        /// <param name="nextPositionCode">下一个地址</param>
+        /// <returns>接口返回结果</returns>
+        /// <exception cref="KnownException"></exception>
+        public static ContinueTaskResponse ContinueTask(string taskCode, string nextPositionCode)
+        {
+            var res = APICaller.CallApi2<ContinueTaskResponse>(AgvUrl + "/rcms/services/rest/hikRpcService/continueTask", new ContinueTaskRequest
+            {
+                reqCode = Guid.NewGuid().ToString().Replace("-", ""),
+                taskCode = taskCode,
+                nextPositionCode = new positionCodeClass()
+                {
+                    positionCode = nextPositionCode,
+                    type = "00"
+                }
+            });
+            if (res.code != AgvResponseCode.Success)
+            {
+                throw new KnownException(res.message, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        #endregion 
+
+        /// <summary>
+        /// 取消任务
+        /// </summary>
+        /// <param name="AGVtaskCode">AGV任务号</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static CancelTaskResponse CancelAgvTask(string AGVtaskCode)
+        {
+            var res = APICaller.CallApi2<CancelTaskResponse>(AgvUrl + "/rcms/services/rest/hikRpcService/cancelTask", new CancelTaskRequest
+            {
+                reqCode = Guid.NewGuid().ToString().Replace("-", ""),
+                taskCode = AGVtaskCode,
+                forceCancel = "0",
+            });
+            if (res.code != AgvResponseCode.Success)
+            {
+                throw new KnownException(res.message, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+
+        /// <summary>
+        ///  AGV取消任务验证
+        /// </summary>
+        /// <param name="sRes"></param>
+        /// <param name="id"></param>
+        /// <param name="agvTask">需要取消任务的AGV任务号</param>
+        /// <returns></returns>
+        public static CancelTaskResponse? CancelAgvTask(SRes<HandleTaskResponse> sRes, int id, string agvTask)
+        {
+            try
+            {
+                var res = AgvApi.CancelAgvTask(agvTask);
+                return res;
+            }
+            catch (Exception ex)
+            {
+                sRes.ResDataList.Add(new HandleTaskResponse()
+                {
+                    IsSuccess = false,
+                    TaskNo = id,
+                    Message = $"AGV错误:{ex.Message}",
+                });
+                return null;
+            }
+        }
+    }
+}

+ 279 - 0
成品库/WCS.WorkEngineering/WebApi/Controllers/AgvController.cs

@@ -0,0 +1,279 @@
+using Microsoft.AspNetCore.Mvc;
+using NetTaste;
+using Newtonsoft.Json;
+using PlcSiemens.Core.Extension;
+using ServiceCenter.Attributes;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.SqlSugars;
+using WCS.Core;
+using WCS.Entity;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.Station;
+using WCS.WorkEngineering.Systems;
+using WCS.WorkEngineering.WebApi.Models.AGV;
+using WCS.WorkEngineering.WebApi.Models.AGV.Request;
+using WCS.WorkEngineering.WebApi.Models.AGV.Response;
+
+namespace WCS.WorkEngineering.WebApi.Controllers
+{
+    /// <summary>
+    /// AGV相关接口控制器
+    /// </summary>
+    [ApiController]
+    [Route("api/[controller]/[action]")]
+    public class AgvController : ControllerBase
+    {
+        /// <summary>
+        ///  AGV任务下发测试
+        /// </summary>
+        /// <param name="type">任务类型</param>
+        /// <param name="code">RFID</param>
+        /// <param name="pos">目标位置</param>
+        /// <returns></returns>
+        [HttpPost]
+        public string AgvDebug(int type, string code, string pos)
+        {
+            try
+            {
+                switch (type)
+                {
+                    case 1:
+                        AgvApi.机台补空(pos, code, "1");
+                        break;
+
+                    case 2:
+                        //AgvApi.机台补满();
+                        break;
+
+                    case 3:
+                        AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1");
+                        break;
+
+                    default:
+                        break;
+                }
+                return "成功";
+            }
+            catch (Exception ex)
+            {
+                return $"Error-----" +
+                      $"{ex.Message}------" +
+                      $"{ex.StackTrace}";
+            }
+        }
+
+        /// <summary>
+        ///  背负式AGV请求出库任务
+        /// </summary>
+        /// <param name="reqDto">请求参数</param>
+        /// <returns></returns>
+        [HttpPost]
+        public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
+        {
+            var key = $"WCS:Lock:AGV:{nameof(ApplyEmptySpool)}";
+            ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
+            try
+            {
+                if (RedisHub.Default.Get(key) != null)
+                {
+                    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                    agvFill.ResMsg = $"[{nameof(ApplyEmptySpool)}]--触发并发管控";
+                }
+                else
+                {
+                    RedisHub.Default.Set(key, nameof(ApplyEmptySpool));
+                    LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}");
+
+                    try
+                    {
+                        agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                        if (!World.IsStart)
+                        {
+                            agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                            agvFill.ResMsg = "WCS初始化中";
+                            return agvFill;
+                        }
+                        //var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
+
+                        //// 检测三个站台是否有货
+                        //obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status)).ToList();
+                        //if (!obj.Any())
+                        //{
+                        //    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                        //    agvFill.ResMsg = "无空轮";
+                        //    return agvFill;
+                        //}
+                        SqlSugarHelper.Do(db =>
+                        {
+                            var res = WmsApi.GetTunnelEmptyConCount();
+
+                            var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
+                                              .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList();
+                            //obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
+                            //if (!obj.Any())
+                            //{
+                            //    agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                            //    agvFill.ResMsg = "无可用取货站点";
+                            //    return;
+                            //}
+
+                            foreach (var item in res.ResDataList)
+                            {
+                                var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
+                                                        .Select(v => v.Targets).SelectMany(v => v)
+                                                        .Where(v => v.HasProtocol(typeof(IStation520)))
+                                                        .Where(v => v.Code is "1012" or "1014" or "1016")
+                                                        .FirstOrDefault();
+                                item.Tunnel = station.ToInt();
+                            }
+                            var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
+                            //var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code));
+                            //var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务");
+                            //var id = db.GetAGVTaskId();
+                            //var agv = new WCS_AgvTaskInfo()
+                            //{
+                            //    ID = id,
+                            //    AgvID = $"HJBK{id}{task.ID}",
+                            //    TaskType = AGVTaskType.CallForMaterial,
+                            //    Status = AGVTaskStatus.NewBuild,
+                            //    Station = dev.Entity.Code,
+                            //    AddWho = "WCS"
+                            //};
+                            ////创建对应的AGV任务
+                            //db.Default.Insertable(agv).SplitTable().ExecuteCommand();
+
+                            //task.AgvTaskID = agv.ID;
+                            //task.Status = Entity.TaskStatus.AGVExecution;
+                            //db.Default.Updateable(task).ExecuteCommand();
+                            //task.AddWCS_TASK_DTL(db, dev.Entity.Code, "AGV", "agv执行中");
+
+                            //agvFill.LocCode = dev.Entity.Code;
+                            //agvFill.SpoolType = "4";
+                            //agvFill.ResMsg = "";
+                            //agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
+                            //agvFill.TaskCode = agv.AgvID;
+                        });
+                    }
+                    catch (Exception ex)
+                    {
+                        agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
+                        agvFill.ResMsg = ex.Message;
+                    }
+                    LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}");
+                }
+            }
+            finally
+            {
+                RedisHub.Default.Del(key);
+            }
+            return agvFill;
+        }
+
+        /// <summary>
+        /// AGV执行回调
+        /// </summary>
+        /// <param name="reqDto"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
+        {
+            var key = $"WCS:Lock:AGV:{nameof(AgvCallback)}";
+            var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" };
+            try
+            {
+                if (RedisHub.Default.Get(key) != null)
+                {
+                    res.code = AgvResponseCode.Error;
+                    res.message = $"[{nameof(AgvCallback)}]--触发并发管控";
+                }
+                else
+                {
+                    RedisHub.Default.Set(key, nameof(AgvCallback));
+                    WCS_TaskInfo taskInfo = null;
+                    try
+                    {
+                        SqlSugarHelper.Do(db =>
+                        {
+                            //跟据AGVid找到对应的AGV任务
+                            var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted);
+                            if (agvTask == null)
+                            {
+                                res.code = AgvResponseCode.Fail;
+                                res.message = "未找到对应的AGV任务";
+
+                            }
+                            else
+                            {
+                                switch (reqDto.method)
+                                {
+                                    //case "start": //表示请求巷道
+                                    //    agvTask.Status = AGVTaskStatus.RequestOrPermission1;
+                                    //    break;
+
+                                    //case "end": //表示请求巷道
+                                    //    agvTask.Status = AGVTaskStatus.RequestOrPermission1;
+                                    //    break;
+
+                                    case "applyContinue": //表示请求巷道
+                                        agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1;
+                                        break;
+
+                                    case "applySecurity": //表示请求放货或取货
+                                        agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2;
+                                        break;
+
+                                    case "hjend_2": //补空任务完成
+                                        agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                        break;
+
+                                    case "endhjBM": //取满任务完成
+                                        agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                        break;
+
+                                    case "end": //二楼出满任务完成
+                                        agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                        break;
+
+                                    case "tcEnd": //机台补空任务完成
+                                        agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                        break;
+
+                                    case "exc_end": //异常信息上抛-值不匹配
+                                        agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                        break;
+
+                                    case "outbin": //小车退出取货位
+                                        agvTask.AgvStatus = AGVTaskStatus.Complete3;
+                                        break;
+
+                                    case "cancel": //取消任务
+                                                   //agvTask.AgvStatus = AGVTaskStatus.Cancel;
+                                        break;
+
+                                    default:
+                                        break;
+                                }
+                                db.Default.Updateable(agvTask).SplitTable().ExecuteCommand();
+                                res.code = AgvResponseCode.Success;
+                                res.message = "成功";
+                            }
+
+
+                        });
+                    }
+                    catch (Exception ex)
+                    {
+                        res.code = AgvResponseCode.Error;
+                        res.message = ex.Message;
+                    }
+                }
+            }
+            finally
+            {
+                RedisHub.Default.Del(key);
+            }
+            return res;
+        }
+    }
+}

+ 125 - 0
成品库/WCS.WorkEngineering/WebApi/Controllers/IwmsApi.cs

@@ -0,0 +1,125 @@
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.WebApi;
+using WCS.WorkEngineering.WebApi.Models.AGV;
+using WCS.WorkEngineering.WebApi.Models.AGV.Request;
+using WCS.WorkEngineering.WebApi.Models.AGV.Response;
+
+namespace WCS.WorkEngineering.WebApi.Controllers
+{
+    public class IwmsApi
+    {
+        private static string _IwmsUrl = null!;
+
+        /// <summary>
+        /// AGV地址
+        /// </summary>
+        public static string IwmsUrl
+        {
+            get
+            {
+                _IwmsUrl ??= RedisHub.Default.Check("IwmsUrl");
+                if (string.IsNullOrEmpty(_IwmsUrl))
+                {
+                    throw new KnownException($"请在Redis配置IwmsUrl", LogLevelEnum.High);
+                }
+                return _IwmsUrl;
+            }
+        }
+
+        /// <summary>
+        ///  满轮出库
+        /// </summary>
+        /// <param name="matCode">物料编号</param>
+        /// <param name="wbCode">取货点位置</param>
+        /// <param name="taskNo">任务号</param>
+        /// <param name="rfid">RFID</param>
+        /// <param name="matNo">材料号</param>
+        /// <param name="isSurplus">改手盘标记</param>
+        /// <param name="isRework">返工标记</param>
+        /// <param name="matFast">快投标记</param>
+        /// <param name="gradeCode">质量等级</param>
+        /// <param name="wetIntoBinCode">仓位号</param>
+        /// <returns></returns>
+        public static zhongTianIntoStockResponse 满轮出库(string matCode, string wbCode, string taskNo, string rfid, string matNo, bool isSurplus, bool isRework, bool matFast, string gradeCode, string wetIntoBinCode)
+        {
+            var zhongTian = new zhongTianIntoStockRequest()
+            {
+                matCode = matCode,
+                wbCode = wbCode,
+                inSpoolFull = "1",
+                getOutEmpty = false,
+                wetIntoReturn = false,
+                isSurplus = isSurplus == false ? "0" : "1",
+                isRework = isRework == false ? "0" : "1",
+                spoolNo = rfid,
+                gradeCode = gradeCode,
+                matFast = matFast == false ? "0" : "1",
+                matNo = matNo,
+                orderProcessLenOut = "0",
+                taskNo = $"RK{taskNo}",
+                returnDesc = "",
+                lockFlag = "0",
+            };
+            if (wetIntoBinCode.Length == 14)
+            {
+                zhongTian.wetInto = true;
+                zhongTian.wetIntoBinCode = wetIntoBinCode;
+                zhongTian.wetIntoSpec = false;
+                zhongTian.wetSpecWbCode = "";
+            }
+            else
+            {
+                zhongTian.wetInto = false;
+                zhongTian.wetIntoBinCode = "";
+                zhongTian.wetIntoSpec = true;
+                zhongTian.wetSpecWbCode = wetIntoBinCode;
+            }
+            return zhongTianIntoStock(zhongTian);
+            //return zhongTianOutStock(new zhongTianOutStockRequest()
+            //{
+            //    matCode = matCode,
+            //    workAreaCode = wbCode,
+            //    outSpoolFull = "1"
+            //});
+        }
+
+        public static zhongTianOutStockResponse 空轮回库(string matCode, string wbCode, bool isSurplus, bool isRework, int taskNo, string RFID)
+        {
+            return zhongTianOutStock(new zhongTianOutStockRequest()
+            {
+                matCode = matCode,
+                workAreaCode = wbCode,
+                outSpoolFull = "0",
+                intoEmpty = false,
+                wetOut = "",
+                wetOutReturn = true,
+                spoolNo = RFID,
+                isSurplus = isSurplus == false ? "0" : "1",
+                isRework = isRework == false ? "0" : "1",
+                reqCode = Guid.NewGuid().ToString().Replace("-", ""),
+                taskNo = $"CK{wbCode}{taskNo}"
+            });
+        }
+
+        public static zhongTianIntoStockResponse zhongTianIntoStock(zhongTianIntoStockRequest req)
+        {
+            var res = APICaller.CallApi2<zhongTianIntoStockResponse>(IwmsUrl + "/databus/publish/zhongTianIntoStock", req);
+            if (res.code != AgvResponseCode.Success)
+            {
+                throw new KnownException(res.message, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        public static zhongTianOutStockResponse zhongTianOutStock(zhongTianOutStockRequest req)
+        {
+            var res = APICaller.CallApi2<zhongTianOutStockResponse>(IwmsUrl + "/databus/publish/zhongTianOutStock", req);
+            if (res.code != AgvResponseCode.Success)
+            {
+                throw new KnownException(res.message, LogLevelEnum.High);
+            }
+            return res;
+        }
+    }
+}

+ 586 - 0
成品库/WCS.WorkEngineering/WebApi/Controllers/WcsController.cs

@@ -0,0 +1,586 @@
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using PlcSiemens.Core.Extension;
+using ServiceCenter;
+using ServiceCenter.Attributes;
+using ServiceCenter.Extensions;
+using ServiceCenter.Redis;
+using ServiceCenter.SqlSugars;
+using System.Net.NetworkInformation;
+using System.Text;
+using WCS.Core;
+using WCS.Entity;
+using WCS.Entity.Protocol.DataStructure;
+using WCS.WorkEngineering.Extensions;
+using WCS.WorkEngineering.Protocol.SRM;
+using WCS.WorkEngineering.Systems;
+using WCS.WorkEngineering.WebApi.Models.WCS.Request;
+using WCS.WorkEngineering.WebApi.Models.WCS.Response;
+using WCS.WorkEngineering.WebApi.Models.WMS.Response;
+
+namespace WCS.WorkEngineering.WebApi.Controllers
+{
+    /// <summary>
+    /// WCS相关接口控制器
+    /// </summary>
+    [ApiController]
+    [Route("api/[controller]/[action]")]
+    public class WcsController : ControllerBase, IDeviceWriter
+    {
+        /// <summary>
+        ///  任务处理接口
+        /// </summary>
+        /// <param name="req"></param>
+        /// <returns></returns>
+        [HttpPost, Log("任务处理接口")]
+        public SRes<HandleTaskResponse> HandleTask([FromBody] HandleTaskRequest req)
+        {
+            SRes<HandleTaskResponse> response = new SRes<HandleTaskResponse>() { ResCode = ResponseStatusCodeEnum.Sucess, ResDataList = new List<HandleTaskResponse>() };
+
+            //取消任务
+            if (req.Type == HandleTaskTypeEnum.取消任务)
+            {
+                SqlSugarHelper.Do(db =>
+                {
+                    foreach (var item in req.TaskIds)
+                    {
+                        var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item).First();
+                        if (task != null)
+                        {
+                            //验证wms是否能取消
+                            SRes res = WmsApi.HandleTaskVerify(response, item, 106);
+                            if (res == null) continue;
+
+                            switch (task.Type)
+                            {
+                                case TaskType.SetPlate:
+                                    if (task.Status != Entity.TaskStatus.WaitingToExecute)
+                                    {
+                                        response.ResDataList.Add(new HandleTaskResponse()
+                                        {
+                                            IsSuccess = false,
+                                            TaskNo = item,
+                                            Message = $"只能取消待执行状态组盘任务",
+                                        });
+                                        continue;
+                                    }
+                                    break;
+
+                                case TaskType.EnterDepot:
+                                    if (task.Status > Entity.TaskStatus.WaitingToExecute && task.Status > Entity.TaskStatus.AGVExecution)
+                                    {
+                                        response.ResDataList.Add(new HandleTaskResponse()
+                                        {
+                                            IsSuccess = false,
+                                            TaskNo = item,
+                                            Message = $"只能取消待执行状态入库任务",
+                                        });
+                                        continue;
+                                    }
+                                    break;
+
+                                case TaskType.OutDepot:
+                                    if (task.Status > Entity.TaskStatus.WaitingToExecute)
+                                    {
+                                        response.ResDataList.Add(new HandleTaskResponse()
+                                        {
+                                            IsSuccess = false,
+                                            TaskNo = item,
+                                            Message = $"只能取消待执行状态出库任务",
+                                        });
+                                        continue;
+                                    }
+
+                                    break;
+
+                                case TaskType.TransferDepot:
+                                    if (task.Status > Entity.TaskStatus.WaitingToExecute)
+                                    {
+                                        response.ResDataList.Add(new HandleTaskResponse()
+                                        {
+                                            IsSuccess = false,
+                                            TaskNo = item,
+                                            Message = $"无法取消{task.Status.GetDescription()}的移库任务,只能取消新建/待执行的移库任务",
+                                        });
+                                        continue;
+                                    }
+                                    break;
+
+                                case TaskType.Delivery:
+
+                                    break;
+
+                                case TaskType.EmptyInit:
+                                    if (task.Status != Entity.TaskStatus.WaitingToExecute)
+                                    {
+                                        response.ResDataList.Add(new HandleTaskResponse()
+                                        {
+                                            IsSuccess = false,
+                                            TaskNo = item,
+                                            Message = $"只能取消待执行状态空轮初始化任务",
+                                        });
+                                        continue;
+                                    }
+                                    break;
+                            }
+
+                            SRes cancelRes = WmsApi.CarryTaskInfo(response, item, 106);
+                            if (cancelRes == null) continue;
+
+                            //找到对应的AGV任务
+                            var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID && v.AgvStatus < AGVTaskStatus.MissionCompleted).SplitTable(v => v.Take(2)).First();
+                            if (agv != null)
+                            {
+                                if (!agv.AgvID.IsNullOrEmpty())
+                                {
+                                    var cancelTaskUpdateRes = AgvApi.CancelAgvTask(response, item, agv.AgvID);
+                                    //if (cancelTaskUpdateRes == null) continue;
+                                }
+                                agv.Status = AGVTaskStatus.Cancel;
+                                agv.AgvStatus = AGVTaskStatus.Cancel;
+                                db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                            }
+                            //更新任务状态
+                            task.Status = Entity.TaskStatus.Cancel;
+                            task.EedTime = DateTime.Now;
+                            task.EditWho = req.User;
+                            task.ManualRemarks = req.ManualRemarks;
+                            task.AddWCS_TASK_DTL(db, "未知", "任务取消");
+                            db.Default.Updateable(task).ExecuteCommand();
+                            task.CompleteOrCancelTasks(db);
+                        }
+                        else
+                        {
+                            response.ResDataList.Add(new HandleTaskResponse()
+                            {
+                                IsSuccess = false,
+                                TaskNo = item,
+                                Message = $"未找到对应任务{item}"
+                            });
+                        }
+                    }
+                });
+            }
+            // 完成任务
+            else if (req.Type == HandleTaskTypeEnum.完成任务)
+            {
+                SqlSugarHelper.Do(db =>
+                {
+                    foreach (var item in req.TaskIds)
+                    {
+                        var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item).First();
+                        if (task != null)
+                        {
+                            if (task.Type == TaskType.OutDepot)
+                            {
+                                SRes res = WmsApi.HandleTaskVerify(response, item, 99);
+                                if (res == null) continue;
+
+                                switch (task.Type)
+                                {
+                                    case TaskType.OutDepot:
+                                        if (task.Status >= Entity.TaskStatus.Finish)
+                                        {
+                                            response.ResDataList.Add(new HandleTaskResponse()
+                                            {
+                                                IsSuccess = false,
+                                                TaskNo = item,
+                                                Message = $"只能完成未完成状态的任务",
+                                            });
+                                            continue;
+                                        }
+                                        break;
+                                }
+
+                                SRes cancelRes = WmsApi.CarryTaskInfo(response, item, 99);
+                                if (cancelRes == null) continue;
+
+                                //找到对应的AGV任务
+                                var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID && v.AgvStatus < AGVTaskStatus.MissionCompleted).SplitTable(v => v.Take(2)).First();
+                                if (agv != null)
+                                {
+                                    //if (!agv.AgvID.IsNullOrEmpty())
+                                    //{
+                                    //    var cancelTaskUpdateRes = CancelAgvTask(response, item, agv.AgvID);
+                                    //    if (cancelTaskUpdateRes == null) continue;
+                                    //}
+                                    agv.Status = AGVTaskStatus.MissionCompleted;
+                                    agv.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                    db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                }
+                                //更新任务状态
+                                task.Status = Entity.TaskStatus.Finish;
+                                task.EedTime = DateTime.Now;
+                                task.EditWho = req.User;
+                                task.ManualRemarks = req.ManualRemarks;
+                                task.AddWCS_TASK_DTL(db, "未知", "任务完成");
+                                db.Default.Updateable(task).ExecuteCommand();
+                                task.CompleteOrCancelTasks(db);
+                            }
+                            else if (task.Type == TaskType.EnterDepot)
+                            {
+                                SRes res = WmsApi.HandleTaskVerify(response, item, 99);
+                                if (res == null) continue;
+
+                                switch (task.Type)
+                                {
+                                    case TaskType.EnterDepot:
+                                        if (task.Status >= Entity.TaskStatus.Finish)
+                                        {
+                                            response.ResDataList.Add(new HandleTaskResponse()
+                                            {
+                                                IsSuccess = false,
+                                                TaskNo = item,
+                                                Message = $"只能完成未完成状态的任务",
+                                            });
+                                            continue;
+                                        }
+                                        if (task.AddrTo.Length < 6)
+                                        {
+                                            response.ResDataList.Add(new HandleTaskResponse()
+                                            {
+                                                IsSuccess = false,
+                                                TaskNo = item,
+                                                Message = $"只能完成已分配货位的任务",
+                                            });
+                                            continue;
+                                        }
+                                        break;
+                                }
+
+                                SRes cancelRes = WmsApi.CarryTaskInfo(response, item, 99);
+                                if (cancelRes == null) continue;
+
+                                //找到对应的AGV任务
+                                var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID && v.AgvStatus < AGVTaskStatus.MissionCompleted).SplitTable(v => v.Take(2)).First();
+                                if (agv != null)
+                                {
+                                    //if (!agv.AgvID.IsNullOrEmpty())
+                                    //{
+                                    //    var cancelTaskUpdateRes = CancelAgvTask(response, item, agv.AgvID);
+                                    //    if (cancelTaskUpdateRes == null) continue;
+                                    //}
+                                    agv.Status = AGVTaskStatus.MissionCompleted;
+                                    agv.AgvStatus = AGVTaskStatus.MissionCompleted;
+                                    db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                                }
+                                //更新任务状态
+                                task.Status = Entity.TaskStatus.Finish;
+                                task.EedTime = DateTime.Now;
+                                task.EditWho = req.User;
+                                task.ManualRemarks = req.ManualRemarks;
+                                task.AddWCS_TASK_DTL(db, "未知", "任务完成");
+                                db.Default.Updateable(task).ExecuteCommand();
+                                task.CompleteOrCancelTasks(db);
+                            }
+                            else
+                            {
+                                response.ResDataList.Add(new HandleTaskResponse()
+                                {
+                                    IsSuccess = false,
+                                    TaskNo = item,
+                                    Message = $"未找到对应任务{item}"
+                                });
+                            }
+                        }
+                    }
+                });
+            }
+            else if (req.Type == HandleTaskTypeEnum.重新下发AGV任务)
+            {
+                SqlSugarHelper.Do(db =>
+                {
+                    foreach (var item in req.TaskIds)
+                    {
+                        var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item).First();
+                        if (task != null)
+                        {
+                            if (task.Type == TaskType.SetPlate) //组盘任务
+                            {
+                                response.ResDataList.Add(new HandleTaskResponse()
+                                {
+                                    IsSuccess = false,
+                                    TaskNo = item,
+                                    Message = $"组盘任务无AGV执行流程",
+                                });
+                                continue;
+                            }
+                            else if (task.Type == TaskType.EnterDepot) //入库任务
+                            {
+                                if (task.Floor == 1) //一楼入库
+                                {
+                                }
+                                else if (task.Floor == 2) //二楼入库
+                                {
+                                    response.ResDataList.Add(new HandleTaskResponse()
+                                    {
+                                        IsSuccess = false,
+                                        TaskNo = item,
+                                        Message = $"二楼入库任务重新下发AGV未实现",
+                                    });
+                                    continue;
+                                }
+                            }
+                            else if (task.Type == TaskType.OutDepot) //出库
+                            {
+                            }
+                            else if (task.Type == TaskType.TransferDepot) //移库
+                            {
+                                response.ResDataList.Add(new HandleTaskResponse()
+                                {
+                                    IsSuccess = false,
+                                    TaskNo = item,
+                                    Message = $"组盘任务无AGV执行流程",
+                                });
+                                continue;
+                            }
+                            else if (task.Type == TaskType.Delivery) //搬运
+                            {
+                                if (task.Floor == 1)
+                                {
+                                }
+                                else if (task.Floor == 2)
+                                {
+                                    response.ResDataList.Add(new HandleTaskResponse()
+                                    {
+                                        IsSuccess = false,
+                                        TaskNo = item,
+                                        Message = $"二楼搬运任务重新下发AGV未实现",
+                                    });
+                                    continue;
+                                }
+                            }
+                            else if (task.Type == TaskType.EmptyInit) //空轮初始化
+                            {
+                                response.ResDataList.Add(new HandleTaskResponse()
+                                {
+                                    IsSuccess = false,
+                                    TaskNo = item,
+                                    Message = $"空轮初始化无AGV执行流程",
+                                });
+                                continue;
+                            }
+
+                            //找到对应的AGV任务
+                            var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID).SplitTable(v => v.Take(2)).First();
+                            if (agv != null)
+                            {
+                                agv.Status = AGVTaskStatus.NewBuild;
+                                agv.AgvStatus = AGVTaskStatus.NewBuild;
+                                db.Default.Updateable(agv).SplitTable().ExecuteCommand();
+                            }
+                            if (task.Floor == 1)
+                            {
+                                task.Status = Entity.TaskStatus.WaitingToExecute;
+                            }
+                            else if (task.Floor == 2)
+                            {
+                                task.Status = Entity.TaskStatus.ConveyorExecution;
+                            }
+
+                            task.AddWCS_TASK_DTL(db, "AGV", "重新下发AGV任务");
+                            db.Default.Updateable(task).ExecuteCommand();
+                        }
+                        else
+                        {
+                            response.ResDataList.Add(new HandleTaskResponse()
+                            {
+                                IsSuccess = false,
+                                TaskNo = item,
+                                Message = $"未找到对应任务{item}"
+                            });
+                        }
+                    }
+                });
+            }
+            return response;
+        }
+
+        /// <summary>
+        ///  设备信息写入接口
+        /// </summary>
+        /// <param name="deviceType">需要写入信息的设备类型</param>
+        /// <param name="devCode">设备编号</param>
+        /// <param name="protocol">设备协议类名</param>
+        /// <param name="propName">写入字段名</param>
+        /// <param name="value">值</param>
+        [HttpPost]
+        public void Write(DeviceTypeEnum deviceType, string devCode, string protocol, string propName, string value)
+        {
+            World.GetSystemInstance<DeviceWriteSystem>().Invoke(new DeviceWriteInfo
+            {
+                DeviceType = deviceType,
+                Code = devCode,
+                Protocol = protocol,
+                Property = propName,
+                Value = value
+            });
+        }
+
+        /// <summary>
+        ///  设备信息写入接口
+        /// </summary>
+        /// <param name="deviceType">需要写入信息的设备类型</param>
+        /// <param name="devCode">设备编号</param>
+        /// <param name="protocol">设备协议类名</param>
+        /// <param name="propName">写入字段名</param>
+        /// <param name="value">值</param>
+        [HttpPost]
+        public void GetDevList()
+        {
+            var a = RedisHub.Monitor.LRange("Packs", 0, 80000);
+            List<DeviceDataPack> packs = new List<DeviceDataPack>();
+            foreach (var item in a)
+            {
+                packs.Add(JsonConvert.DeserializeObject<DeviceDataPack>(item));
+            }
+        }
+
+        /// <summary>
+        ///  获取设备配置信息接口
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet]
+        public List<Device> GetDeviceList()
+        {
+            return Device.All.ToList();
+        }
+
+        /// <summary>
+        ///  获取设备信息
+        /// </summary>
+        /// <param name="type"></param>
+        /// <param name="name">设备名称</param>
+        /// <returns></returns>
+        [HttpGet]
+        public object GetDeviceInfo(string type, string name)
+        {
+            var remoteIpAddress = HttpContext.Connection.RemoteIpAddress.ToString();
+            var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke(new Tuple<string, string>(type, name));
+            return obj;
+        }
+
+        /// <summary>
+        ///  堆垛机测试
+        /// </summary>
+        /// <param name="srmcod">堆垛机编号</param>
+        /// <param name="typeEnum">任务类型</param>
+        /// <param name="value1">起始行</param>
+        /// <param name="value2">起始列</param>
+        /// <param name="value3">起始层</param>
+        /// <param name="value4">目标行</param>
+        /// <param name="value5">目标列</param>
+        /// <param name="value6">目标层</param>
+        [HttpPost]
+        public void SrmDeBug(string srmcod, SrmTaskType typeEnum, short value1, short value2, short value3, short value4, short value5, short value6)
+        {
+            World.GetSystemInstance<SrmDebugSystem>().Invoke(new SrmDebugInfo
+            {
+                SrmCode = srmcod,
+                srmTaskType = typeEnum,
+                SLine = value1,
+                SCol = value2,
+                SLayer = value3,
+                ELine = value4,
+                ECol = value5,
+                ELayer = value6
+            });
+        }
+
+        #region 设备IP相关
+
+        /// <summary>
+        ///  获取设备Ip集合
+        /// </summary>
+        /// <returns>设备Ip集合</returns>
+        [HttpGet]
+        public List<string> GetDeviceIpList()
+        {
+            if (!ServiceHub.DeviceIPList.Any()) throw new Exception("未配置任何Ip");
+            return ServiceHub.DeviceIPList;
+        }
+
+        /// <summary>
+        ///  获取设备IP检测结果
+        /// </summary>
+        /// <returns>设备IP检测结果</returns>
+        [HttpGet]
+        public List<DeviceIpTestResults> DeviceIpTest()
+        {
+            if (!ServiceHub.DeviceIPList.Any()) throw new Exception("未配置任何Ip");
+            List<DeviceIpTestResults> deviceIpTestResults = new List<DeviceIpTestResults>();
+            ServiceHub.DeviceIPList.ForEach(ip =>
+            {
+                deviceIpTestResults.Add(new DeviceIpTestResults
+                {
+                    Ip = ip,
+                    Result = PingIpOrDomainName(ip)
+                });
+            });
+
+            return deviceIpTestResults;
+        }
+
+        /// <summary>
+        /// 检查Ip是否正常联通
+        /// </summary>
+        /// <param name="strIpOrDName">输入参数,表示IP地址或域名</param>
+        /// <returns></returns>
+        public static bool PingIpOrDomainName(string strIpOrDName)
+        {
+            try
+
+            {
+                Ping objPingSender = new Ping();
+
+                PingOptions objPinOptions = new PingOptions();
+
+                objPinOptions.DontFragment = true;
+
+                string data = "";
+
+                byte[] buffer = Encoding.UTF8.GetBytes(data);
+
+                int intTimeout = 120;
+
+                PingReply objPinReply = objPingSender.Send(strIpOrDName, intTimeout, buffer, objPinOptions);
+
+                string strInfo = objPinReply.Status.ToString();
+
+                if (strInfo == "Success")
+
+                {
+                    return true;
+                }
+                else
+
+                {
+                    return false;
+                }
+            }
+            catch (Exception)
+
+            {
+                return false;
+            }
+        }
+
+        #endregion 设备IP相关
+    }
+
+    public interface IDeviceWriter
+    {
+        [HttpPost]
+        void Write(DeviceTypeEnum deviceType, string devCode, string protocol, string propName, string value);
+    }
+
+    /// <summary>
+    ///  设备Ip通讯检测结构
+    /// </summary>
+    public class DeviceIpTestResults
+    {
+        public string Ip { get; set; }
+
+        public bool Result { get; set; }
+    }
+}

+ 423 - 0
成品库/WCS.WorkEngineering/WebApi/Controllers/WmsApi.cs

@@ -0,0 +1,423 @@
+using ServiceCenter;
+using ServiceCenter.Extensions;
+using ServiceCenter.Logs;
+using ServiceCenter.Redis;
+using ServiceCenter.WebApi;
+using WCS.WorkEngineering.WebApi.Models.AGV.Response;
+using WCS.WorkEngineering.WebApi.Models.WCS.Response;
+using WCS.WorkEngineering.WebApi.Models.WMS.Request;
+using WCS.WorkEngineering.WebApi.Models.WMS.Response;
+
+namespace WCS.WorkEngineering.WebApi.Controllers
+{
+    /// <summary>
+    /// AGV相关接口控制器
+    /// </summary>
+
+    public static class WmsApi
+    {
+        private static string _WMSUrl = null!;
+        private static string _wareHouseId = null!;
+
+        /// <summary>
+        ///  WMS URL
+        /// </summary>
+        public static string WMSUrl
+        {
+            get
+            {
+                _WMSUrl ??= RedisHub.Default.Check("WMSUrl");
+                if (string.IsNullOrEmpty(_WMSUrl))
+                {
+                    throw new KnownException($"请在Redis配置WMSUrl", LogLevelEnum.High);
+                }
+                return _WMSUrl;
+            }
+        }
+
+        /// <summary>
+        /// 仓库编号
+        /// </summary>
+        public static string wareHouseId = ServiceHub.WarehouseName;
+
+        /// <summary>
+        ///  上传重量等信息
+        /// </summary>
+        /// <param name="taskCode">任务号</param>
+        /// <param name="weight">rfid</param>
+        /// <returns></returns>
+        public static SRes WcsUploadInfo(int taskCode, decimal weight) => WcsUploadInfo(taskCode, weight, "");
+
+        /// <summary>
+        ///  上传重量等信息
+        /// </summary>
+        /// <param name="taskCode">任务号</param>
+        /// <param name="RFID">重量</param>
+        /// <returns></returns>
+        public static SRes WcsUploadInfo(int taskCode, string RFID) => WcsUploadInfo(taskCode, 0, RFID);
+
+        /// <summary>
+        ///   上传重量等信息
+        /// </summary>
+        /// <param name="taskCode">任务号</param>
+        /// <param name="weight">重量</param>
+        /// <param name="RFID">rfid</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes WcsUploadInfo(int taskCode, decimal weight, string RFID)
+        {
+            var res = APICaller.CallApi2<SRes>(WMSUrl + "/api/Hj/WcsUploadInfo", new WcsUploadInfoRequest
+            {
+                TaskCode = taskCode,
+                Weight = weight,
+                RFID = RFID
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  获取巷道
+        /// </summary>
+        /// <param name="wcsTaskNum">WMS任务ID</param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        public static SRes<string> GetTunnelPriorityList(int wcsTaskNum)
+        {
+            var res = APICaller.CallApi2<SRes<string>>(WMSUrl + "/api/Hj/GetTunnelPriorityList", new GetTunnelPriorityListRequest
+            {
+                TaskNum = wcsTaskNum,
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  分配货位
+        /// </summary>
+        /// <param name="wcsTaskNum">WMS任务ID</param>
+        /// <param name="tunnel">货位</param>
+        /// <param name="device">设备号</param>
+        /// <param name="size"></param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        public static SRes<ApplyStockInLocResponse> GetLocalIn(int wcsTaskNum, string tunnel, string device, int size)
+        {
+            var res = APICaller.CallApi2<SRes<ApplyStockInLocResponse>>(WMSUrl + "/api/FJ/ApplyStockInLoc", new ApplyStockInLocRequest
+            {
+                TaskNum = wcsTaskNum,
+                TunnelNum = tunnel.GetLastDigit(),
+                PickUpEquipmentNo = device.ToString(),
+                Height = size
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  堆垛机出库任务执行完成
+        /// </summary>
+        /// <param name="taskNum"></param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes<int> SrmPickOutCompleted(int taskNum)
+        {
+            var res = APICaller.CallApi2<SRes<int>>(WMSUrl + "/api/Hj/SrmPickOutCompleted", new SrmPickOutCompletedRequest
+            {
+                TaskNum = taskNum,
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  一楼空工字轮申请出库
+        /// </summary>
+        /// <param name="outEndPostion">出库位置</param>
+        /// <returns></returns>
+        public static SRes ApplyStockOutTask(string outEndPostion) => ApplyStockOutTask(outEndPostion, 2);
+
+        /// <summary>
+        ///  申请出库任务
+        /// </summary>
+        /// <param name="outEndPostion">出库位置</param>
+        /// <param name="outType">出库类型</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes ApplyStockOutTask(string outEndPostion, int outType)
+        {
+            var request = new ApplyStockOutTaskRequest
+            {
+                OutEndPostion = outEndPostion,
+                OutType = outType,
+                WarehouseCode = wareHouseId,
+            };
+            switch (outEndPostion)
+            {
+                case "1012":
+                    request.Tunnel = "1";
+                    break;
+
+                case "1014":
+                    request.Tunnel = "2";
+                    break;
+
+                case "1016":
+                    request.Tunnel = "3";
+                    break;
+            }
+            var res = APICaller.CallApi2<SRes>(WMSUrl + "/api/Hj/ApplyStockOutTask", request);
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  获取各巷道剩余空轮数量
+        /// </summary>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes<GetTunnelEmptyConResponse> GetTunnelEmptyConCount()
+        {
+            var res = APICaller.CallApi2<SRes<GetTunnelEmptyConResponse>>(WMSUrl + "/api/Hj/GetTunnelEmptyConCount", new GetTunnelEmptyConCountRequest { });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  完成任务
+        /// </summary>
+        /// <param name="taskNo"></param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes<int> CompleteTask(int taskNo)
+        {
+            var res = APICaller.CallApi2<SRes<int>>(WMSUrl + "/api/fj/CompleteTask", new CompleteTaskRequest
+            {
+                TaskNum = taskNo,
+                OperationType = Models.WMS.Request.CompleteTask.自动完成,
+                WCSUpdateName = "WCS"
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  二深位获取移库任务
+        /// </summary>
+        /// <param name="taskNo">任务</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes<AddWcsMoveTaskResponse> AddWcsMoveTask(int taskNo)
+        {
+            var res = APICaller.CallApi2<SRes<AddWcsMoveTaskResponse>>(WMSUrl + "/api/Hj/AddWcsMoveTask", new CompleteTaskRequest
+            {
+                TaskNum = taskNo,
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        /// 向WMS获取入库任务 一次单卷
+        /// </summary>
+        /// <param name="barcode">产品条码</param>
+        /// <param name="devCode">设备条码</param>
+        /// <param name="getTunnel"></param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        public static I_WCS_GetInTaskResponse I_WCS_GetInTask(string barcode, string devCode, bool getTunnel = false)
+        {
+            var res = APICaller.CallApi<I_WCS_GetInTaskResponse>(WMSUrl + "/api/Task/I_WCS_GetInTask", new List<I_WCS_GetInTaskRequest>()
+            {
+                new I_WCS_GetInTaskRequest(){
+                     ContainerBarCode = barcode,
+                     WareHouseId = wareHouseId,
+                     EquipmentNo = devCode,
+                     Memo1 = getTunnel ? "1" : "" //1:分巷道  2:分货位
+                }
+            });
+            if (!res.ResType) throw new KnownException(res.ResMessage, LogLevelEnum.High);
+
+            return res;
+        }
+
+        /// <summary>
+        ///  处理任务验证接口
+        /// </summary>
+        /// <param name="taskNo">需要处理的任务进行验证</param>
+        /// <param name="state">目标状态</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes HandleTaskVerify(List<int> taskNo, int state)
+        {
+            var res = APICaller.CallApi2<SRes>(WMSUrl + "/api/Hj/CancelTaskVerify", new CancelTaskVerifyRequest
+            {
+                TaskNo = taskNo,
+                State = state
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  处理任务接口
+        /// </summary>
+        /// <param name="taskNo">处理</param>
+        /// <param name="state">目标状态</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes CarryTaskInfo(List<int> taskNo, int state)
+        {
+            var res = APICaller.CallApi2<SRes>(WMSUrl + "/api/Hj/CarryTaskInfo", new CancelTaskVerifyRequest
+            {
+                TaskNo = taskNo,
+                State = state
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  WMS完成或取消任务验证
+        /// </summary>
+        /// <param name="sRes"></param>
+        /// <param name="id"></param>
+        /// <param name="type">99完成,106取消</param>
+        /// <returns></returns>
+        public static SRes? HandleTaskVerify(SRes<HandleTaskResponse> sRes, int id, int type)
+        {
+            try
+            {
+                var res = WmsApi.HandleTaskVerify(new List<int>() { id }, type);
+                return res;
+            }
+            catch (Exception ex)
+            {
+                sRes.ResDataList.Add(new HandleTaskResponse()
+                {
+                    IsSuccess = false,
+                    TaskNo = id,
+                    Message = $"WMS错误:{ex.Message}",
+                });
+                return null;
+            }
+        }
+
+        /// <summary>
+        ///  WMS完成或取消任务执行
+        /// </summary>
+        /// <param name="sRes"></param>
+        /// <param name="id"></param>
+        /// <param name="type">99完成,106取消</param>
+        /// <returns></returns>
+        public static SRes? CarryTaskInfo(SRes<HandleTaskResponse> sRes, int id, int type)
+        {
+            try
+            {
+                var res = WmsApi.CarryTaskInfo(new List<int>() { id }, type);
+                return res;
+            }
+            catch (Exception ex)
+            {
+                sRes.ResDataList.Add(new HandleTaskResponse()
+                {
+                    IsSuccess = false,
+                    TaskNo = id,
+                    Message = $"WMS错误:{ex.Message}",
+                });
+                return null;
+            }
+        }
+
+        /// <summary>
+        ///  工字轮/芯股进入主线扫码
+        /// </summary>
+        /// <param name="codeList">工字轮条码组</param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes? OneFloorWorkerBuildEmptyPalletsStock(OneFloorWorkerBuildEmptyPalletsStockRequest reqDto)
+        {
+            var res = APICaller.CallApi2<SRes>(WMSUrl + "/api/FJ/OneFloorWorkerBuildEmptyPalletsStock", new OneFloorWorkerBuildEmptyPalletsStockRequest
+            {
+                PalletCode = reqDto.PalletCode,
+                PalletType = reqDto.PalletType,
+                StartLoc = reqDto.StartLoc,
+                WareCode = GetWareCode(reqDto.StartLoc),
+                PalletNum = "1"
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+
+        /// <summary>
+        ///  获取仓库号
+        /// </summary>
+        public static string GetWareCode(string add)
+        {
+            return add switch
+            {
+                "2532" => "1N",
+                "2527" => "1N",
+                "2528" => "1N",
+                "2732" => "1S",
+                "2727" => "1S",
+                "2728" => "1S",
+                _ => "",
+            };
+        }
+
+        /// <summary>
+        ///  工字轮/芯股进入主线扫码
+        /// </summary>
+        /// <param name="reqDto"></param>
+        /// <param name="equNo"></param>
+        /// <returns></returns>
+        /// <exception cref="KnownException"></exception>
+        public static SRes EnteMainLine(List<string> reqDto, string equNo)
+        {
+            var res = APICaller.CallApi<SRes>(WMSUrl + "/api/FJ/EnteMainLine", new FJEnteMainLineRequest
+            {
+                IShapedWheelCodes = reqDto,
+                equNo = equNo
+            });
+            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
+            {
+                throw new KnownException(res.ResMsg, LogLevelEnum.High);
+            }
+            return res;
+        }
+    }
+}

+ 28 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/AgvResponseCode.cs

@@ -0,0 +1,28 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV
+{
+    /// <summary>
+    ///  AGV 返回结果code值枚举
+    /// </summary>
+    public class AgvResponseCode
+    {
+        /// <summary>
+        ///  成功
+        /// </summary>
+        public static string Success { get; set; } = "0";
+
+        /// <summary>
+        ///  失败
+        /// </summary>
+        public static string Fail { get; set; } = "1";
+
+        /// <summary>
+        ///  重复提交
+        /// </summary>
+        public static string Repeat { get; set; } = "6";
+
+        /// <summary>
+        ///  失败,未知异常
+        /// </summary>
+        public static string Error { get; set; } = "99";
+    }
+}

+ 10 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/AddWcsMoveTaskRequest.cs

@@ -0,0 +1,10 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    /// <summary>
+    ///  获取移库任务请求参数
+    /// </summary>
+    public class AddWcsMoveTaskRequest
+    {
+        public int TaskNum { get; set; }
+    }
+}

+ 118 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/AgvCallbackRequest.cs

@@ -0,0 +1,118 @@
+using WCS.Service;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    public class AgvCallbackRequest
+    {
+        /// <summary>
+        /// 请求编号,每个请求都要一个唯一编号, 同一个请求重复提交, 使用同一编号
+        /// </summary>
+        public string reqCode { get; set; }
+
+        /// <summary>
+        ///  请求站台
+        /// </summary>
+        public string callCode { get; set; }
+
+        /// <summary>
+        /// 请求时间戳,格式: “yyyy-MM-dd HH:mm:ss”
+        /// </summary>
+        public string reqTime { get; set; }
+
+        /// <summary>
+        /// 地码 X 坐标(mm):任务完成时有值
+        /// </summary>
+        public decimal cooX { get; set; }
+
+        /// <summary>
+        /// 地码 Y 坐标(mm):任务完成时有值
+        /// </summary>
+        public decimal cooY { get; set; }
+
+        /// <summary>
+        /// 当前位置编号
+        /// </summary>
+        public string currentPositionCode { get; set; }
+
+        /// <summary>
+        /// 自定义字段
+        /// </summary>
+        public string data { get; set; }
+
+        /// <summary>
+        /// 地图编号
+        /// </summary>
+        public string mapCode { get; set; }
+
+        /// <summary>
+        /// 地码编号:任务完成时有值
+        /// </summary>
+        public string mapDataCode { get; set; }
+
+        /// <summary>
+        /// 仓位编号:叉车与CTU任务时有值
+        /// </summary>
+        public string stgBinCode { get; set; }
+
+        /// <summary>
+        /// 方法名,申请放货、请求取货、
+        /// </summary>
+        public string method { get; set; }
+
+        /// <summary>
+        /// 货架编号:背货架时有值
+        /// </summary>
+        public string podCode { get; set; }
+
+        /// <summary>
+        /// “180”,”0”,”90”,”-90” 分别对应地图的”左”,”右”,”上”,”下”:任务完成时有值
+        /// </summary>
+        public string podDir { get; set; }
+
+        /// <summary>
+        /// 物料编号
+        /// </summary>
+        public string materialLot { get; set; }
+
+        /// <summary>
+        /// AGV编号(同 agvCode )
+        /// </summary>
+        public string robotCode { get; set; }
+
+        /// <summary>
+        /// 当前任务单号
+        /// </summary>
+        public string taskCode { get; set; }
+
+        /// <summary>
+        /// 工作位
+        /// </summary>
+        public string wbCode { get; set; }
+
+        /// <summary>
+        /// 容器编号
+        /// </summary>
+        public string ctnrCode { get; set; }
+
+        /// <summary>
+        /// 容器类型
+        /// </summary>
+        public string ctnrTyp { get; set; }
+
+        /// <summary>
+        /// 巷道编号
+        /// </summary>
+        public string roadWayCode { get; set; }
+
+        /// <summary>
+        /// 巷道内顺序号巷道尾是0,到巷道头依次递增1
+        /// </summary>
+        public string seq { get; set; }
+
+        /// <summary>
+        /// 设备编号
+        /// </summary>
+        public string eqpCode { get; set; }
+
+    }
+}

+ 18 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/ApplyEmptySpoolRequest.cs

@@ -0,0 +1,18 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    /// <summary>
+    ///  背负式AGV补空请求参数
+    /// </summary>
+    public class AgvFillEmptySpaceRequest
+    {
+        /// <summary>
+        ///  请求号
+        /// </summary>
+        public string Reqid { get; set; }
+
+        /// <summary>
+        /// 仓库编号
+        /// </summary>
+        public string WareCode { get; set; }
+    }
+}

+ 50 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/CancelTaskRequest.cs

@@ -0,0 +1,50 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    /// <summary>
+    ///  取消任务
+    /// </summary>
+    public class CancelTaskRequest
+    {
+        /// <summary>
+        ///  请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+
+        /// <summary>
+        ///  求时间截 格式: “yyyy-MM-dd HH:mm:ss”。
+        /// </summary>
+        public string reqTime { get; set; }
+
+        /// <summary>
+        ///  客户端编号,如PDA,HCWMS等。
+        /// </summary>
+        public string clientCode { get; set; }
+
+        /// <summary>
+        ///  令牌号, 由调度系统颁发
+        /// </summary>
+        public string tokenCode { get; set; }
+
+        /// <summary>
+        ///  取消类型 0表示:取消后货架直接放地上
+        ///  1表示:AGV仍然背着货架, 根据回库区域执行回库指令, 只有潜伏车和CTU车支持。
+        ///  默认的取消模式为0
+        /// </summary>
+        public string forceCancel { get; set; }
+
+        /// <summary>
+        ///  forcecancel=1时有意义,回库区域编号, 如果为空,采用货架配置的库区。
+        /// </summary>
+        public string matterArea { get; set; }
+
+        /// <summary>
+        ///  取消该AGV正在执行的任务单
+        /// </summary>
+        public string agvCode { get; set; }
+
+        /// <summary>
+        /// 任务单编号, 取消该任务单
+        /// </summary>
+        public string taskCode { get; set; }
+    }
+}

+ 68 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/ContinueTaskRequest.cs

@@ -0,0 +1,68 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    /// <summary>
+    /// Agv继续执行任务请求参数
+    /// </summary>
+    public class ContinueTaskRequest
+    {
+        /// <summary>
+        ///  请求编号,每个请求都要一个唯一编号, 同一个请求重复提交, 使用同一编号。
+        /// </summary>
+        public string reqCode { get; set; }
+
+        /// <summary>
+        ///  请求时间截 格式: “yyyy-MM-dd HH:mm:ss”。
+        /// </summary>
+        public string reqTime { get; set; }
+
+        /// <summary>
+        ///  客户端编号,如PDA,HCWMS等。
+        /// </summary>
+        public string clientCode { get; set; }
+
+        /// <summary>
+        ///  令牌号, 由调度系统颁发。
+        /// </summary>
+        public string tokenCode { get; set; }
+
+        /// <summary>
+        ///  工作位,与RCS-2000端配置的位置名称一致。
+        /// </summary>
+        public string wbCode { get; set; }
+
+        /// <summary>
+        ///  货架号,采用货架号触发的方式。
+        /// </summary>
+        public string podCode { get; set; }
+
+        /// <summary>
+        ///  AGV编号,采用 AGV编号触发的方式。
+        /// </summary>
+        public string agvCode { get; set; }
+
+        /// <summary>
+        ///  任务单号,选填, 不填系统自动生 成,必须为 64 位 UUID
+        /// </summary>
+        public string taskCode { get; set; }
+
+        /// <summary>
+        ///  下一个子任务的序列,指定第几个子任务开始执行,校验子任务执行是否正确。不填默认执行下一个子任务。
+        /// </summary>
+        public string taskSeq { get; set; }
+
+        /// <summary>
+        ///  下一个位置信息,在任务类型中配置外部设置时需要传入,否则不需要设置。待现场地图部署、配置完成后可获取
+        /// </summary>
+        public positionCodeClass nextPositionCode { get; set; }
+
+        /// <summary>
+        ///  根据type填写,呼叫站点/策略编号等
+        /// </summary>
+        public string positionCode { get; set; }
+
+        /// <summary>
+        /// 对象类型定义: 00:代表 nextPositionCode是一个位置 02:代表nextPositionCode是一个策略
+        /// </summary>
+        public string type { get; set; }
+    }
+}

+ 62 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/CopperLineAgvTaskStockInToIWmsRequest.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    public class CopperLineAgvTaskStockInToIWmsRequest
+    {
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string matCode { get; set; }
+        /// <summary>
+        /// 工作站编号
+        /// </summary>
+        public string workAreaCode { get; set; }
+        /// <summary>
+        /// 空/满工字轮标记(满工字轮:1空工字轮:0)
+        /// </summary>
+        public string outSpoolFull { get; set; }
+        /// <summary>
+        /// 取空补满标记
+        /// </summary>
+        public bool intoEmpty { get; set; }
+        /// <summary>
+        /// 湿拉出库标记
+        /// </summary>
+        public string wetOut { get; set; }
+        /// <summary>
+        /// 湿拉退料出库标记
+        /// </summary>
+        public string wetOutReturn { get; set; }
+        /// <summary>
+        /// 改手盘标记
+        /// </summary>
+        public string isSurplus { get; set; }
+        /// <summary>
+        /// 返工标记
+        /// </summary>
+        public string isRework { get; set; }
+        /// <summary>
+        /// 材料号
+        /// </summary>
+        public string matNo { get; set; }
+        /// <summary>
+        /// RFID号
+        /// </summary>
+        public string spoolNo { get; set; }
+        /// <summary>
+        /// 质量状态标记
+        /// </summary>
+        public string gradeCode { get; set; }
+        /// <summary>
+        /// 快投标记
+        /// </summary>
+        public string matFast { get; set; }
+        /// <summary>
+        /// 任务号
+        /// </summary>
+        public string taskNo { get; set; }
+    }
+}

+ 82 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/CopperLineAgvTaskStockOutToIWmsRequest.cs

@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    public class CopperLineAgvTaskStockOutToIWmsRequest
+    {
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string matCode { get; set; }
+        /// <summary>
+        /// 工作站编号(机台号、立库点位编号)
+        /// </summary>
+        public string wbCode { get; set; }
+        /// <summary>
+        /// 空/满工字轮入库标记(空工字轮:0,满工字轮:1,半工字轮:2)
+        /// </summary>
+        public string inSpoolFull { get; set; }
+        /// <summary>
+        /// 取满补空标记
+        /// </summary>
+        public bool getOutEmpty { get; set; }
+        /// <summary>
+        /// 湿拉上线标记
+        /// </summary>
+        public bool wetInto { get; set; }
+        /// <summary>
+        /// 湿拉特殊上线标记
+        /// </summary>
+        public bool wetIntoSpec { get; set; }
+        /// <summary>
+        /// 湿拉退料入库标记
+        /// </summary>
+        public bool wetIntoReturn { get; set; }
+        /// <summary>
+        /// 湿拉特殊上线点位号
+        /// </summary>
+        public string wetSpecWbCode { get; set; }
+        /// <summary>
+        /// 改手盘标记
+        /// </summary>
+        public string isSurplus { get; set; }
+        /// <summary>
+        /// 返工标记
+        /// </summary>
+        public string isRework { get; set; }
+        /// <summary>
+        /// 材料号
+        /// </summary>
+        public string matNo { get; set; }
+        /// <summary>
+        /// RFID号
+        /// </summary>
+        public string spoolNo { get; set; }
+        /// <summary>
+        /// 质量状态标记
+        /// </summary>
+        public string gradeCode { get; set; }
+        /// <summary>
+        /// 快投标记
+        /// </summary>
+        public string matFast { get; set; }
+        /// <summary>
+        /// 长度
+        /// </summary>
+        public string orderProcessLenOut { get; set; }
+        /// <summary>
+        /// 任务号
+        /// </summary>
+        public string taskNo { get; set; }
+        /// <summary>
+        /// 退料原因
+        /// </summary>
+        public string returnDesc { get; set; }
+        /// <summary>
+        /// 是否锁定
+        /// </summary>
+        public string lockFlag { get; set; }
+    }
+}

+ 200 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/GenAgvSchedulingTaskRequest.cs

@@ -0,0 +1,200 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    /// <summary>
+    ///  生成任务单接口
+    /// </summary>
+    public class GenAgvSchedulingTaskRequest
+    {
+        /// <summary>
+        /// 请求编号,每个请求都要一个唯一编号, 同一个请求重复提交, 使用同一编号。
+        /// </summary>
+        public string reqCode { get; set; }
+
+        /// <summary>
+        /// 请求时间截 格式: “yyyy-MM-dd HH:mm:ss”
+        /// </summary>
+        public string reqTime { get; set; }
+
+        /// <summary>
+        /// 客户端编号,如PDA,HCWMS等
+        /// </summary>
+        public string clientCode { get; set; }
+
+        /// <summary>
+        /// 令牌号, 由调度系统颁发
+        /// </summary>
+        public string tokenCode { get; set; }
+
+        /// <summary>
+        /// 任务类型
+        /// </summary>
+        public string taskTyp { get; set; }
+
+        /// <summary>
+        /// 容器类型(叉车/CTU专用)叉车项目必传
+        /// </summary>
+        public string ctnrTyp { get; set; }
+
+        /// <summary>
+        ///  RFID
+        /// </summary>
+        public string ctnrCode { get; set; }
+
+        /// <summary>
+        /// 接口名称
+        /// </summary>
+        public string interfaceName { get; set; }
+
+        /// <summary>
+        /// 任务模式
+        /// </summary>
+        public string taskMode { get; set; }
+
+        /// <summary>
+        ///  合金任务模板
+        /// </summary>
+        public string hjTaskTy { get; set; }
+
+        /// <summary>
+        /// 工作位
+        /// </summary>
+        public string wbCode { get; set; }
+
+        /// <summary>
+        /// 位置路径
+        /// </summary>
+        public List<positionCodeClass> positionCodePath { get; set; }
+
+        /// <summary>
+        ///  位置类型
+        /// </summary>
+        public string type { get; set; }
+
+        /// <summary>
+        /// 货架编号
+        /// </summary>
+        public string podCode { get; set; }
+
+        /// <summary>
+        /// “180”,”0”,”90”,”-90”
+        /// </summary>
+        public string podDir { get; set; }
+
+        /// <summary>
+        /// 货架类型, 传空时表示随机找个货架
+        /// </summary>
+        public string podTyp { get; set; }
+
+        /// <summary>
+        /// 物料批次或货架上的物料唯一编码
+        /// </summary>
+        public string materialLot { get; set; }
+
+        /// <summary>
+        /// 优先级,从(1~127)级,最大优先级最高
+        /// </summary>
+        public string priority { get; set; }
+
+        /// <summary>
+        /// 任务单号,选填, 不填系统自动生成,UUID小于等于64位
+        /// </summary>
+        public string taskCode { get; set; }
+
+        /// <summary>
+        /// AGV编号,填写表示指定某一编号的AGV执行该任务
+        /// </summary>
+        public string agvCode { get; set; }
+
+        /// <summary>
+        /// 组编号
+        /// </summary>
+        public string groupId { get; set; }
+
+        /// <summary>
+        /// 自定义字段.JSON格式
+        /// </summary>
+        public string data { get; set; }
+    }
+
+    /// <summary>
+    ///  AGV生成任务单请求TaskTyp对应枚举
+    /// </summary>
+    public class GenAgvSchedulingTaskRequestTaskTyp
+    {
+        /// <summary>
+        ///  厂内货架搬运
+        /// </summary>
+        public string 厂内货架搬运 { get; set; } = "F01";
+
+        /// <summary>
+        ///  厂内货架空满交换
+        /// </summary>
+        public string 厂内货架空满交换 { get; set; } = "F02";
+
+        /// <summary>
+        ///  辊筒搬运接驳
+        /// </summary>
+        public string 辊筒搬运接驳 { get; set; } = "F03";
+
+        /// <summary>
+        ///  厂内货架出库AGV待命
+        /// </summary>
+        public string 厂内货架出库AGV待命 { get; set; } = "F04";
+
+        /// <summary>
+        ///  旋转货架
+        /// </summary>
+        public string 旋转货架 { get; set; } = "F05";
+
+        /// <summary>
+        ///  厂内电梯任务
+        /// </summary>
+        public string 厂内电梯任务 { get; set; } = "F06";
+
+        /// <summary>
+        ///  以下为叉车专用任务类型高位货架到工作台
+        /// </summary>
+        public string 以下为叉车专用任务类型高位货架到工作台 { get; set; } = "F11";
+
+        /// <summary>
+        ///  工作台到高位货架
+        /// </summary>
+        public string 工作台到高位货架 { get; set; } = "F12";
+
+        /// <summary>
+        ///  工作台到巷道
+        /// </summary>
+        public string 工作台到巷道 { get; set; } = "F14";
+
+        /// <summary>
+        ///  高位货架到工作台接驳
+        /// </summary>
+        public string 高位货架到工作台接驳 { get; set; } = "F15";
+
+        /// <summary>
+        ///  工作台到高位货架接驳
+        /// </summary>
+        public string 工作台到高位货架接驳 { get; set; } = "F16";
+
+        /// <summary>
+        ///  巷道到工作台接驳
+        /// </summary>
+        public string 巷道到工作台接驳 { get; set; } = "F17";
+
+        /// <summary>
+        ///  工作台到巷道接驳
+        /// </summary>
+        public string 工作台到巷道接驳 { get; set; } = "F18";
+
+        /// <summary>
+        ///  叉车电梯主任务
+        /// </summary>
+        public string 叉车电梯主任务 { get; set; } = "F20";
+    }
+
+    public class positionCodeClass
+    {
+        public string positionCode { get; set; }
+        public string type { get; set; }
+    }
+}

+ 103 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/zhongTianIntoStockRequest.cs

@@ -0,0 +1,103 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+    /// <summary>
+    ///  合金二楼下发AGV入库任务
+    /// </summary>
+    public class zhongTianIntoStockRequest
+    {
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string matCode { get; set; }
+
+        /// <summary>
+        /// 工作站编号
+        /// </summary>
+        public string wbCode { get; set; }
+
+        /// <summary>
+        /// 空/满工字轮入库标记
+        /// </summary>
+        public string inSpoolFull { get; set; }
+
+        /// <summary>
+        /// 取满补空标记
+        /// </summary>
+        public bool getOutEmpty { get; set; }
+
+        /// <summary>
+        /// 湿拉上线标记
+        /// </summary>
+        public bool wetInto { get; set; }
+
+        /// <summary>
+        /// 湿拉特殊上线标记
+        /// </summary>
+        public bool wetIntoSpec { get; set; }
+
+        /// <summary>
+        /// 湿拉退料入库标记
+        /// </summary>
+        public bool wetIntoReturn { get; set; }
+
+        /// <summary>
+        /// 湿拉特殊上线点位号
+        /// </summary>
+        public string wetSpecWbCode { get; set; }
+
+        /// <summary>
+        /// 改手盘标记
+        /// </summary>
+        public string isSurplus { get; set; }
+
+        /// <summary>
+        /// 返工标记
+        /// </summary>
+        public string isRework { get; set; }
+
+        /// <summary>
+        /// 材料号
+        /// </summary>
+        public string matNo { get; set; }
+
+        /// <summary>
+        /// RFID号
+        /// </summary>
+        public string spoolNo { get; set; }
+
+        /// <summary>
+        /// 质量状态标记
+        /// </summary>
+        public string gradeCode { get; set; }
+
+        /// <summary>
+        /// 快投标记
+        /// </summary>
+        public string matFast { get; set; }
+
+        /// <summary>
+        /// 长度
+        /// </summary>
+        public string orderProcessLenOut { get; set; }
+
+        /// <summary>
+        /// 任务号
+        /// </summary>
+        public string taskNo { get; set; }
+
+        /// <summary>
+        /// 退料原因
+        /// </summary>
+        public string returnDesc { get; set; }
+
+        /// <summary>
+        /// 是否锁定
+        /// </summary>
+        public string lockFlag { get; set; }
+
+        /// <summary>
+        ///  仓位号
+        /// </summary>
+        public string wetIntoBinCode { get; set; }
+    }
+}

+ 79 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Request/zhongTianOutStockRequest.cs

@@ -0,0 +1,79 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Request
+{
+ 
+    /// <summary>
+    ///  合金二楼下发AGV出库任务
+    /// </summary>
+    public class zhongTianOutStockRequest
+    {
+        /// <summary>
+        /// 请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+
+        /// <summary>
+        /// 物料编码
+        /// </summary>
+        public string matCode { get; set; }
+
+        /// <summary>
+        /// 工作站编号
+        /// </summary>
+        public string workAreaCode { get; set; }
+
+        /// <summary>
+        /// 空/满工字轮标记
+        /// </summary>
+        public string outSpoolFull { get; set; }
+
+        /// <summary>
+        /// 取空补满标记
+        /// </summary>
+        public bool intoEmpty { get; set; }
+
+        /// <summary>
+        /// 湿拉出库标记
+        /// </summary>
+        public string wetOut { get; set; }
+
+        /// <summary>
+        /// 湿拉退料出库标记
+        /// </summary>
+        public bool wetOutReturn { get; set; }
+
+        /// <summary>
+        /// 改手盘标记
+        /// </summary>
+        public string isSurplus { get; set; }
+
+        /// <summary>
+        /// 返工标记
+        /// </summary>
+        public string isRework { get; set; }
+
+        /// <summary>
+        /// 材料号
+        /// </summary>
+        public string matNo { get; set; }
+
+        /// <summary>
+        /// RFID号
+        /// </summary>
+        public string spoolNo { get; set; }
+
+        /// <summary>
+        /// 质量状态标记
+        /// </summary>
+        public string gradeCode { get; set; }
+
+        /// <summary>
+        /// 快投标记
+        /// </summary>
+        public string matFast { get; set; }
+
+        /// <summary>
+        /// 任务号
+        /// </summary>
+        public string taskNo { get; set; }
+    }
+}

+ 29 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/AddWcsMoveTaskResponse.cs

@@ -0,0 +1,29 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    /// <summary>
+    ///  获取移库任务
+    /// </summary>
+    public class AddWcsMoveTaskResponse
+    {
+        /// <summary>
+        /// 0:失败;1:允许2升位执行;2:执行移库任务;3:一深位有出库任务
+        /// </summary>
+        public WmsApiMoveTask ResType { get; set; } = 0;
+
+        /// <summary>
+        /// 一深位货位号
+        /// </summary>
+        public string CellNo { get; set; }
+    }
+
+    /// <summary>
+    /// 获取移库任务返回结果
+    /// </summary>
+    public enum WmsApiMoveTask
+    {
+        失败 = 0,
+        允许2升位执行 = 1,
+        执行移库任务 = 2,
+        一深位有出库任务 = 3
+    }
+}

+ 35 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/ApplyEmptySpoolResponse.cs

@@ -0,0 +1,35 @@
+using WCS.WorkEngineering.WebApi.Models.WMS.Response;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    /// <summary>
+    ///  agv补空返回参数
+    /// </summary>
+    public class ApplyEmptySpoolResponse
+    {
+        /// <summary>
+        ///  站台编号
+        /// </summary>
+        public string LocCode { get; set; }
+
+        /// <summary>
+        ///  工字轮类型
+        /// </summary>
+        public string SpoolType { get; set; }
+
+        /// <summary>
+        ///  返回状态码
+        /// </summary>
+        public ResponseStatusCodeEnum ResCode { get; set; }
+
+        /// <summary>
+        ///  描述信息
+        /// </summary>
+        public string ResMsg { get; set; }
+
+        /// <summary>
+        ///  任务号
+        /// </summary>
+        public string TaskCode { get; set; }
+    }
+}

+ 27 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/CancelTaskResponse.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    /// <summary>
+    ///  取消任务返回接口
+    /// </summary>
+    public class CancelTaskResponse
+    {
+        /// <summary>
+        /// 返回码
+        /// </summary>
+        public string code { get; set; }
+        /// <summary>
+        /// 返回消息
+        /// </summary>
+        public string message { get; set; }
+        /// <summary>
+        /// 请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+    }
+}

+ 25 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/ContinueTaskResponse.cs

@@ -0,0 +1,25 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    /// <summary>
+    ///  Agv继续执行任务返回参数
+    /// </summary>
+    public class ContinueTaskResponse
+    {
+        /// <summary>
+        ///  返回码 对应类:AgvContinueTaskResponseCode
+        /// </summary>
+        public string code { get; set; }
+
+        /// <summary>
+        ///  返回消息
+        /// </summary>
+        public string message { get; set; }
+
+        /// <summary>
+        ///  请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+    }
+
+   
+}

+ 26 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/GenAgvSchedulingTaskResponse.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    public class GenAgvSchedulingTaskResponse
+    {
+        /// <summary>
+        /// 返回码
+        /// </summary>
+        public string code { get; set; }
+        /// <summary>
+        /// 返回消息
+        /// </summary>
+        public string message { get; set; }
+        /// <summary>
+        /// 请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+        /// <summary>
+        /// 自定义返回(返回任务单号)
+        /// </summary>
+        public string data { get; set; }
+    }
+}

+ 22 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/agvCallbackResponse.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    public class AgvCallbackResponse
+    {
+        /// <summary>
+        /// 返回码 1:允许执行 0:不允许执行
+        /// </summary>
+        public string code { get; set; } = "0";
+        /// <summary>
+        /// 返回消息
+        /// </summary>
+        public string message { get; set; } = "成功";
+        /// <summary>
+        /// 请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+    }
+}

+ 28 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/zhongTianIntoStockResponse.cs

@@ -0,0 +1,28 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class zhongTianIntoStockResponse
+    {
+        /// <summary>
+        /// 返回码
+        /// </summary>
+        public string code { get; set; }
+
+        /// <summary>
+        /// 自定义返回(返回任务单号)
+        /// </summary>
+        public string data { get; set; }
+
+        /// <summary>
+        /// 返回消息
+        /// </summary>
+        public string message { get; set; }
+
+        /// <summary>
+        /// 请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+    }
+}

+ 25 - 0
成品库/WCS.WorkEngineering/WebApi/Models/AGV/Response/zhongTianOutStockResponse.cs

@@ -0,0 +1,25 @@
+namespace WCS.WorkEngineering.WebApi.Models.AGV.Response
+{
+    public class zhongTianOutStockResponse
+    {
+        /// <summary>
+        /// 返回码
+        /// </summary>
+        public string code { get; set; }
+
+        /// <summary>
+        /// 自定义返回(返回任务单号)
+        /// </summary>
+        public string data { get; set; }
+
+        /// <summary>
+        /// 返回消息
+        /// </summary>
+        public string message { get; set; }
+
+        /// <summary>
+        /// 请求编号
+        /// </summary>
+        public string reqCode { get; set; }
+    }
+}

+ 46 - 0
成品库/WCS.WorkEngineering/WebApi/Models/WCS/Request/HandleTaskRequest.cs

@@ -0,0 +1,46 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace WCS.WorkEngineering.WebApi.Models.WCS.Request
+{
+    /// <summary>
+    ///  处理任务请求参数
+    /// </summary>
+    public class HandleTaskRequest
+    {
+        /// <summary>
+        ///  任务号
+        /// </summary>
+        [Required]
+        public List<int> TaskIds { get; set; }
+
+        /// <summary>
+        ///  处理类型
+        /// </summary>
+        [Required]
+        public HandleTaskTypeEnum Type { get; set; }
+
+        /// <summary>
+        ///  用户
+        /// </summary>
+        public string User { get; set; }
+
+        /// <summary>
+        ///  手动处理备注
+        /// </summary>
+        public string ManualRemarks { get; set; }
+
+        /// <summary>
+        /// 优先级
+        /// </summary>
+        public int Priority { get; set; }
+    }
+
+    public enum HandleTaskTypeEnum
+    {
+        取消任务 = 1,
+        完成任务 = 2,
+        重新下发AGV任务 = 3,
+        调整优先级 = 4
+        //重新下发出库AGV任务 = 1,
+    }
+}

+ 23 - 0
成品库/WCS.WorkEngineering/WebApi/Models/WCS/Response/HandleTaskResponse.cs

@@ -0,0 +1,23 @@
+namespace WCS.WorkEngineering.WebApi.Models.WCS.Response
+{
+    /// <summary>
+    ///  处理任务接口返回内容
+    /// </summary>
+    public class HandleTaskResponse
+    {
+        /// <summary>
+        ///  是否成功
+        /// </summary>
+        public bool IsSuccess { get; set; }
+
+        /// <summary>
+        /// 任务号
+        /// </summary>
+        public int TaskNo { get; set; }
+
+        /// <summary>
+        ///  消息
+        /// </summary>
+        public string Message { get; set; }
+    }
+}

+ 32 - 0
成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/ApplyStockInLocRequest.cs

@@ -0,0 +1,32 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
+{
+    /// <summary>
+    /// 分配货位请求实体
+    /// </summary>
+    public class ApplyStockInLocRequest
+    {
+        /// <summary>
+        /// WMS任务号
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public int TaskNum { get; set; }
+
+        /// <summary>
+        /// 巷道号
+        /// </summary>
+        public int TunnelNum { get; set; }
+
+        /// <summary>
+        /// 取货地点设备编号
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public string PickUpEquipmentNo { get; set; }
+
+        /// <summary>
+        ///  大小货 1表示小货 2表示大货
+        /// </summary>
+        public int Height { get; set; }
+    }
+}

+ 40 - 0
成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/ApplyStockOutTaskRequest.cs

@@ -0,0 +1,40 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
+{
+    public class ApplyStockOutTaskRequest
+    {
+        /// <summary>
+        /// 出库位置
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public string OutEndPostion { get; set; }
+
+        /// <summary>
+        /// 出库类型(0.无效参数;1.物料出库;2.空托盘出库;3.空工字轮出库;)
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public int OutType { get; set; }
+
+        /// <summary>
+        /// 仓库编码
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public string WarehouseCode { get; set; }
+
+        /// <summary>
+        /// 巷道
+        /// </summary>
+        public string Tunnel { get; set; } = "";
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        public string Memo1 { get; set; } = "";
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        public string Memo2 { get; set; } = "";
+    }
+}

+ 20 - 0
成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/CancelTaskVerifyRequest.cs

@@ -0,0 +1,20 @@
+using WCS.WorkEngineering.WebApi.Models.WCS.Request;
+
+namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
+{
+    /// <summary>
+    ///  取消或完成任务验证请求
+    /// </summary>
+    public class CancelTaskVerifyRequest
+    {
+        /// <summary>
+        ///  任务号集合
+        /// </summary>
+        public List<int> TaskNo { get; set; }
+
+        /// <summary>
+        ///  目标状态
+        /// </summary>
+        public int State { get; set; }
+    }
+}

+ 47 - 0
成品库/WCS.WorkEngineering/WebApi/Models/WMS/Request/CompleteTaskRequest.cs

@@ -0,0 +1,47 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace WCS.WorkEngineering.WebApi.Models.WMS.Request
+{
+    /// <summary>
+    ///  完成任务请求
+    /// </summary>
+    public class CompleteTaskRequest
+    {
+        /// <summary>
+        /// WMS任务号
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public int TaskNum { get; set; }
+
+        /// <summary>
+        /// 操作类型(1.自动完成 2.手动完成)
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public CompleteTask OperationType { get; set; }
+
+        /// <summary>
+        /// WCS操作人名称
+        /// </summary>
+        [Required(ErrorMessage = "{0} 不可为空")]
+        public string WCSUpdateName { get; set; }
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        public string Memo1 { get; set; } = "";
+
+        /// <summary>
+        /// 备用
+        /// </summary>
+        public string Memo2 { get; set; } = "";
+    }
+
+    /// <summary>
+    ///  完成任务类型
+    /// </summary>
+    public enum CompleteTask
+    {
+        自动完成 = 1,
+        手动完成 = 2
+    }
+}

Vissa filer visades inte eftersom för många filer har ändrats