浏览代码

add reservoir initialize routine releated

chenzk 4 天之前
父节点
当前提交
7244d4257d

+ 2 - 2
Framework/Common/Common.csproj

@@ -410,8 +410,8 @@
     <Compile Include="Net\JetTcpClient.cs" />
     <Compile Include="Net\NetStateObject.cs" />
     <Compile Include="OperationCenter\IInterlockChecker.cs" />
-    <Compile Include="Persistent\Metal\MetalPersistentManager.cs" />
-    <Compile Include="Persistent\Metal\MetalPersistentValue.cs" />
+    <Compile Include="Persistent\Metal\PlatingCellPersistentManager.cs" />
+    <Compile Include="Persistent\Metal\PlatingCellPersistentValue.cs" />
     <Compile Include="Persistent\PersistentManager.cs" />
     <Compile Include="Persistent\Prewet\PrewetPersistentManager.cs" />
     <Compile Include="Persistent\Prewet\PrewetPersistentValue.cs" />

+ 1 - 1
Framework/Common/DataCenter/IQueryDataService.cs

@@ -149,7 +149,7 @@ namespace MECF.Framework.Common.DataCenter
     [ServiceKnownType(typeof(StandardHotMetalDeviceData))]
     [ServiceKnownType(typeof(CompactMembranMetalDeviceData))]
     [ServiceKnownType(typeof(StandardHotMetalDeviceData))]
-    [ServiceKnownType(typeof(MetalPersistentValue))] 
+    [ServiceKnownType(typeof(PlatingCellPersistentValue))] 
     [ServiceKnownType(typeof(TCPersistentValue))]
     [ServiceKnownType(typeof(ReplenData[]))]
     [ServiceKnownType(typeof(List<ModuleMaterial>))]

+ 43 - 43
Framework/Common/Persistent/Metal/MetalPersistentManager.cs

@@ -14,10 +14,10 @@ using System.Threading.Tasks;
 
 namespace MECF.Framework.Common.Persistent.Reservoirs
 {
-    public class MetalPersistentManager : Singleton<MetalPersistentManager>
+    public class PlatingCellPersistentManager : Singleton<PlatingCellPersistentManager>
     {
         #region 内部变量
-        private Dictionary<string, MetalPersistentValue> _persistentValueDic = new Dictionary<string, MetalPersistentValue>();
+        private Dictionary<string, PlatingCellPersistentValue> _persistentValueDic = new Dictionary<string, PlatingCellPersistentValue>();
         private Dictionary<string, string> _persistentValuePathDic = new Dictionary<string, string>();
         #endregion
         /// <summary>
@@ -27,43 +27,43 @@ namespace MECF.Framework.Common.Persistent.Reservoirs
         {
             try
             {
-                List<string> installedModules= MetalItemManager.Instance.InstalledModules;
-                foreach (string module in installedModules)
-                {
-                    string foldStr = PathManager.GetCfgDir() + $"Persistent\\Metals";
-                    if (!Directory.Exists(foldStr))
-                    {
-                        Directory.CreateDirectory(foldStr);
-                    }
-                    string str = $"{foldStr}\\{module}Persistent.xml";
-                    _persistentValuePathDic[module] = str;
-                    if (File.Exists(str))
-                    {
-                        MetalPersistentValue metalPersistentValue = CustomXmlSerializer.Deserialize<MetalPersistentValue>(new FileInfo(str));
-                        if (metalPersistentValue != null)
-                        {
-                            _persistentValueDic[module] = metalPersistentValue;
-                        }
-                    }
-                    else
-                    {
-                        MetalPersistentValue persistentValue = new MetalPersistentValue();
-                        persistentValue.Name = module;
-                        _persistentValueDic[module] = persistentValue;
-                        UpdatePersistentValue(module);
-                    }
+                List<string> installedModules= PlatingCellItemManager.Instance.InstalledModules;
+                foreach (string module in installedModules)
+                {
+                    string foldStr = PathManager.GetCfgDir() + $"Persistent\\PlatingCells";
+                    if (!Directory.Exists(foldStr))
+                    {
+                        Directory.CreateDirectory(foldStr);
+                    }
+                    string str = $"{foldStr}\\{module}Persistent.xml";
+                    _persistentValuePathDic[module] = str;
+                    if (File.Exists(str))
+                    {
+                        PlatingCellPersistentValue platingCellPersistentValue = CustomXmlSerializer.Deserialize<PlatingCellPersistentValue>(new FileInfo(str));
+                        if (platingCellPersistentValue != null)
+                        {
+                            _persistentValueDic[module] = platingCellPersistentValue;
+                        }
+                    }
+                    else
+                    {
+                        PlatingCellPersistentValue persistentValue = new PlatingCellPersistentValue();
+                        persistentValue.Name = module;
+                        _persistentValueDic[module] = persistentValue;
+                        UpdatePersistentValue(module);
+                    }
                 }
             }
             catch (Exception ex)
             {
-                LOG.WriteLog(eEvent.ERR_METAL, "System", "Load MetalsPersistent xml exception");
+                LOG.WriteLog(eEvent.ERR_PLATINGCELL, "System", "Load PlatingCellsPersistent xml exception");
             }
         }
         /// <summary>
-        /// 获取Metal Persistent数值
+        /// 获取PlatingCell Persistent数值
         /// </summary>
         /// <returns></returns>
-        public MetalPersistentValue GetMetalPersistentValue(string module)
+        public PlatingCellPersistentValue GetPlatingCellPersistentValue(string module)
         {
             if( _persistentValueDic.ContainsKey(module)) 
             { 
@@ -80,20 +80,20 @@ namespace MECF.Framework.Common.Persistent.Reservoirs
         /// <returns></returns>
         public void UpdatePersistentValue(string module)
         {
-            if (_persistentValueDic.ContainsKey(module))
-            {
-                try
-                {
-                    CustomXmlSerializer.Serialize(_persistentValueDic[module], _persistentValuePathDic[module]);
-                }
-                catch (Exception ex)
-                {
-                    LOG.WriteLog(eEvent.ERR_METAL, module, "Update MetalsPersistent xml file excepetion");
-                }
+            if (_persistentValueDic.ContainsKey(module))
+            {
+                try
+                {
+                    CustomXmlSerializer.Serialize(_persistentValueDic[module], _persistentValuePathDic[module]);
+                }
+                catch (Exception ex)
+                {
+                    LOG.WriteLog(eEvent.ERR_PLATINGCELL, module, "Update PlatingCellsPersistent xml file excepetion");
+                }
             }
-            else
-            {
-                LOG.WriteLog(eEvent.ERR_METAL, module, "Update MetalsPersistent xml file excepetion");
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_PLATINGCELL, module, "Update PlatingCellsPersistent xml file excepetion");
             }
         }
     }

+ 5 - 5
Framework/Common/Persistent/Metal/MetalPersistentValue.cs

@@ -9,7 +9,7 @@ using System.Xml.Serialization;
 
 namespace MECF.Framework.Common.Persistent.Reservoirs
 {
-    public class MetalPersistentValue : NotifiableItem
+    public class PlatingCellPersistentValue : NotifiableItem
     {
         #region 内部变量
         /// <summary>
@@ -25,9 +25,9 @@ namespace MECF.Framework.Common.Persistent.Reservoirs
         /// </summary>
         private string _recipeOperatingMode;
         /// <summary>
-        /// MetalWaferSize
+        /// PlatingCellWaferSize
         /// </summary>
-        private int _metalWaferSize;
+        private int _platingCellWaferSize;
         #endregion
         /// <summary>
         /// 名称
@@ -43,9 +43,9 @@ namespace MECF.Framework.Common.Persistent.Reservoirs
         /// </summary>
         public string RecipeOperatingMode { get { return _recipeOperatingMode; } set { _recipeOperatingMode = value; InvokePropertyChanged(nameof(RecipeOperatingMode)); } }
         /// <summary>
-        /// MetalWaferSize
+        /// PlatingCellWaferSize
         /// </summary>
-        public int MetalWaferSize { get { return _metalWaferSize; } set { _metalWaferSize = value; InvokePropertyChanged(nameof(MetalWaferSize)); } }
+        public int PlatingCellWaferSize { get { return _platingCellWaferSize; } set { _platingCellWaferSize = value; InvokePropertyChanged(nameof(PlatingCellWaferSize)); } }
     }
 }
 

+ 1 - 1
Framework/Common/Persistent/PersistentManager.cs

@@ -25,7 +25,7 @@ namespace MECF.Framework.Common.Persistent
             PrewetPersistentManager.Instance.Initialize();
             RinsePersistentManager.Instance.Initialize();
             ReservoirsPersistentManager.Instance.Initialize();
-            MetalPersistentManager.Instance.Initialize();
+            PlatingCellPersistentManager.Instance.Initialize();
             TCPersistentManager.Instance.Initialize();
             ReplenPersistentManager.Instance.Initialize();
             VpwCellPersistentManager.Instance.Initialize();

+ 3 - 0
PunkHPX8_Core/EventDefine.cs

@@ -163,6 +163,9 @@ namespace Aitex.Core.RT.Log{
 		INFO_VPWMAIN = 6042,
 		WARN_VPWMAIN = 6043,
 		ERR_VPWMAIN = 6044,
+		INFO_PLATINGCELL = 6045,
+		WARN_PLATINGCELL = 6046,
+		ERR_PLATINGCELL = 6047,
 		ERROR_EFEM_COMMUNICATION = 10101001,
 		ERROR_EFEM_NOREADY = 10101002,
 		ERROR_EFEM_SORC_NOWAF = 10101003,

+ 68 - 0
PunkHPX8_MainPages/ViewModels/DMReservoirViewModel.cs

@@ -88,6 +88,10 @@ namespace PunkHPX8_MainPages.ViewModels
         /// DIValveMaxOnTime
         /// </summary>
         private double _diValveMaxOnTime;
+        /// <summary>
+        /// 是否补水异常
+        /// </summary>
+        private bool _isDIReplenFault;
 
 
         /// <summary>
@@ -214,6 +218,40 @@ namespace PunkHPX8_MainPages.ViewModels
             get { return _isCALowLevel; }
             set { SetProperty(ref _isCALowLevel, value); }
         }
+
+        /// <summary>
+        /// 单次注水最大时长
+        /// </summary>
+        public double DIValveMaxOnTime
+        {
+            get { return _diValveMaxOnTime; }
+            set { SetProperty(ref _diValveMaxOnTime, value); }
+        }
+        /// <summary>
+        /// 手动注水时长
+        /// </summary>
+        public int ManualFillSeconds
+        {
+            get { return _manualFillSeconds; }
+            set { SetProperty(ref _manualFillSeconds, value); }
+        }
+        /// <summary>
+        /// 正在手动注水
+        /// </summary>
+        public bool IsManualReplen
+        {
+            get { return _isManualReplen; }
+            set { SetProperty(ref _isManualReplen, value); }
+        }
+        /// <summary>
+        /// 是否补水异常
+        /// </summary>
+        public bool IsDIReplenFault
+        {
+            get { return _isDIReplenFault; }
+            set { SetProperty(ref _isDIReplenFault, value); }
+        }
+
         #endregion
 
 
@@ -222,6 +260,8 @@ namespace PunkHPX8_MainPages.ViewModels
         public ICommand CAPumpSpeedSetCommand { get; set; }
         public ICommand ANPumpSpeedSetCommand { get; set; }
         public ICommand ReturnFlowOpenPercentSetCommand { get; set; }
+        public ICommand ResetTotalCommand { get; set; }
+        public ICommand ManualDireplenCommand { get; set; }
 
         #endregion
 
@@ -231,6 +271,8 @@ namespace PunkHPX8_MainPages.ViewModels
             CAPumpSpeedSetCommand = new DelegateCommand<object>(CAPumpSpeedSetAction);
             ANPumpSpeedSetCommand = new DelegateCommand<object>(ANPumpSpeedSetAction);
             ReturnFlowOpenPercentSetCommand = new DelegateCommand<object>(ReturnFlowOpenPercentSetAction);
+            ResetTotalCommand = new DelegateCommand<object>(ResetTotalAction);
+            ManualDireplenCommand = new DelegateCommand<object>(ManualDireplenAction);
         }
 
         #region 命令方法
@@ -266,6 +308,21 @@ namespace PunkHPX8_MainPages.ViewModels
         {
             InvokeClient.Instance.Service.DoOperation($"{Module}.ReturnValvePercent", InputRetrunFlowOpenPercent);
         }
+        /// <summary>
+        /// 重置TotalTime
+        /// </summary>
+        private void ResetTotalAction(object param)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{Module}.ResetTotalTime");
+        }
+        /// <summary>
+        /// 手动注水
+        /// </summary>
+        /// <param name="param"></param>
+        private void ManualDireplenAction(object param)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{Module}.ManualCADiReplen", ManualFillSeconds);
+        }
         #endregion
 
         public void LoadData(string systemName)
@@ -281,6 +338,11 @@ namespace PunkHPX8_MainPages.ViewModels
             _rtDataKeys.Add($"{Module}.IsCAHighLevel");
             _rtDataKeys.Add($"{Module}.IsCALowLevel");
             _rtDataKeys.Add($"{Module}.TemperatureControllerData");
+
+            _rtDataKeys.Add($"{Module}.DIValveMaxOnTime");
+            _rtDataKeys.Add($"{Module}.IsManualCAReplen");
+            _rtDataKeys.Add($"{Module}.IsDIReplenPerfillTimeOut");
+            _rtDataKeys.Add($"{Module}.IsDIReplenMaxTimeOut");
             if (_timer == null)
             {
                 _timer = new DispatcherTimer();
@@ -326,6 +388,12 @@ namespace PunkHPX8_MainPages.ViewModels
                     IsCALowLevel = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsCALowLevel");
 
 
+                    DIValveMaxOnTime = CommonFunction.GetValue<double>(_rtDataValueDic, $"{Module}.DIValveMaxOnTime");
+                    IsManualReplen = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsManualCAReplen");
+                    IsDIReplenFault = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsDIReplenPerfillTimeOut") 
+                        || CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsDIReplenMaxTimeOut"); 
+
+
                 }
             }
         }

+ 33 - 6
PunkHPX8_RT/Config/LogDefine.json

@@ -1405,7 +1405,7 @@
     "Module": "WAGO",
     "Note": "WAGO Error"
   },
-    {
+  {
     "Id": 6039,
     "Level": "Info",
     "LogEnum": "INFO_VPW",
@@ -1414,7 +1414,7 @@
     "Module": "VPW",
     "Note": "VPW Info"
   },
-    {
+  {
     "Id": 6040,
     "Level": "Warning",
     "LogEnum": "WARN_VPW",
@@ -1423,7 +1423,7 @@
     "Module": "VPW",
     "Note": "VPW Warning"
   },
-    {
+  {
     "Id": 6041,
     "Level": "Error",
     "LogEnum": "ERR_VPW",
@@ -1432,7 +1432,7 @@
     "Module": "VPW",
     "Note": "VPW Error"
   },
-     {
+  {
     "Id": 6042,
     "Level": "Info",
     "LogEnum": "INFO_VPWMAIN",
@@ -1441,7 +1441,7 @@
     "Module": "VPWMAIN",
     "Note": "VPWMAIN Info"
   },
-    {
+  {
     "Id": 6043,
     "Level": "Warning",
     "LogEnum": "WARN_VPWMAIN",
@@ -1450,7 +1450,7 @@
     "Module": "VPWMAIN",
     "Note": "VPWMAIN Warning"
   },
-    {
+  {
     "Id": 6044,
     "Level": "Error",
     "LogEnum": "ERR_VPWMAIN",
@@ -1460,6 +1460,33 @@
     "Note": "VPWMAIN Error"
   },
   {
+    "Id": 6045,
+    "Level": "Info",
+    "LogEnum": "INFO_PLATINGCELL",
+    "GlobalDescription_zh": "{0}。",
+    "GlobalDescription_en": "{0}.",
+    "Module": "PLATINGCELL",
+    "Note": "PLATINGCELL Info"
+  },
+  {
+    "Id": 6046,
+    "Level": "Warning",
+    "LogEnum": "WARN_PLATINGCELL",
+    "GlobalDescription_zh": "{0}。",
+    "GlobalDescription_en": "{0}.",
+    "Module": "PLATINGCELL",
+    "Note": "PLATINGCELL Warning"
+  },
+  {
+    "Id": 6047,
+    "Level": "Error",
+    "LogEnum": "ERR_PLATINGCELL",
+    "GlobalDescription_zh": "{0}。",
+    "GlobalDescription_en": "{0}.",
+    "Module": "PLATINGCELL",
+    "Note": "PLATINGCELL Error"
+  },
+  {
     "Id": 10101001,
     "Level": "Error",
     "LogEnum": "ERROR_EFEM_COMMUNICATION",

+ 13 - 0
PunkHPX8_RT/Config/System.sccfg

@@ -347,6 +347,10 @@
 			<config default="0,0,1.5022,94.782" name="CALevelCurve" nameView="CALevelCurve" description="Level curve" max="" min="" paramter="" tag="" unit="" type="String" />
 			<config default="95" name="CAHighLevel" nameView="CAHighLevel" description="CA High Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
 			<config default="10" name="CALowLevel" nameView="CALowLevel" description="CA Low Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
+			<config default="16" name="DIValveMaxOnTime" nameView="DIValveMaxOnTime" description="DI Valve Max Time in period " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="5" name="DIValveMaxOnTimePerFill" nameView="DIValveMaxOnTimePerFill" description="DI Valve Max Time per fill " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="24" name="DIValveMaxOnTimePeriod" nameView="DIValveMaxOnTimePeriod" description="DI Valve Max Time in period " max="48" min="0" paramter="" tag="" unit="hour" type="Double" />
+		
 		</configs>
 		<configs name="Reservoir2" nameView="Reservoir2">
 			<config default="5.0" name="CAMainFlowFaultLow" nameView="CAMainFlowFaultLow" description="CA Main Flow Fault Low" max="30" min="0" paramter="" tag="" unit="" type="Double"></config>
@@ -354,6 +358,9 @@
 			<config default="0,0,1.5022,94.782" name="CALevelCurve" nameView="CALevelCurve" description="Level curve" max="" min="" paramter="" tag="" unit="" type="String" />
 			<config default="95" name="CAHighLevel" nameView="CAHighLevel" description="CA High Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
 			<config default="10" name="CALowLevel" nameView="CALowLevel" description="CA Low Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
+			<config default="16" name="DIValveMaxOnTime" nameView="DIValveMaxOnTime" description="DI Valve Max Time in period " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="5" name="DIValveMaxOnTimePerFill" nameView="DIValveMaxOnTimePerFill" description="DI Valve Max Time per fill " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="24" name="DIValveMaxOnTimePeriod" nameView="DIValveMaxOnTimePeriod" description="DI Valve Max Time in period " max="48" min="0" paramter="" tag="" unit="hour" type="Double" />
 		</configs>
 		<configs name="Reservoir3" nameView="Reservoir3">
 			<config default="5.0" name="CAMainFlowFaultLow" nameView="CAMainFlowFaultLow" description="CA Main Flow Fault Low" max="30" min="0" paramter="" tag="" unit="" type="Double"></config>
@@ -361,6 +368,9 @@
 			<config default="0,0,1.5022,94.782" name="CALevelCurve" nameView="CALevelCurve" description="Level curve" max="" min="" paramter="" tag="" unit="" type="String" />
 			<config default="95" name="CAHighLevel" nameView="CAHighLevel" description="CA High Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
 			<config default="10" name="CALowLevel" nameView="CALowLevel" description="CA Low Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
+			<config default="16" name="DIValveMaxOnTime" nameView="DIValveMaxOnTime" description="DI Valve Max Time in period " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="5" name="DIValveMaxOnTimePerFill" nameView="DIValveMaxOnTimePerFill" description="DI Valve Max Time per fill " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="24" name="DIValveMaxOnTimePeriod" nameView="DIValveMaxOnTimePeriod" description="DI Valve Max Time in period " max="48" min="0" paramter="" tag="" unit="hour" type="Double" />
 		</configs>
 		<configs name="Reservoir4" nameView="Reservoir4">
 			<config default="5.0" name="CAMainFlowFaultLow" nameView="CAMainFlowFaultLow" description="CA Main Flow Fault Low" max="30" min="0" paramter="" tag="" unit="" type="Double"></config>
@@ -368,6 +378,9 @@
 			<config default="0,0,1.5022,94.782" name="CALevelCurve" nameView="CALevelCurve" description="Level curve" max="" min="" paramter="" tag="" unit="" type="String" />
 			<config default="95" name="CAHighLevel" nameView="CAHighLevel" description="CA High Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
 			<config default="10" name="CALowLevel" nameView="CALowLevel" description="CA Low Level" max="100" min="0" paramter="" tag="" unit="" type="Double" />
+			<config default="16" name="DIValveMaxOnTime" nameView="DIValveMaxOnTime" description="DI Valve Max Time in period " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="5" name="DIValveMaxOnTimePerFill" nameView="DIValveMaxOnTimePerFill" description="DI Valve Max Time per fill " max="50" min="0" paramter="" tag="" unit="minute" type="Double" />
+			<config default="24" name="DIValveMaxOnTimePeriod" nameView="DIValveMaxOnTimePeriod" description="DI Valve Max Time in period " max="48" min="0" paramter="" tag="" unit="hour" type="Double" />
 		</configs>
 	</configs>
 </root>

+ 27 - 0
PunkHPX8_RT/Devices/DeviceManager.cs

@@ -12,6 +12,7 @@ using PunkHPX8_RT.Devices.AXIS;
 using PunkHPX8_RT.Devices.EFEM;
 using PunkHPX8_RT.Devices.Facilities;
 using PunkHPX8_RT.Devices.LinMot;
+using PunkHPX8_RT.Devices.PlatingCell;
 using PunkHPX8_RT.Devices.PowerSupplier;
 using PunkHPX8_RT.Devices.Reservoir;
 using PunkHPX8_RT.Devices.Resistivity;
@@ -67,6 +68,7 @@ namespace PunkHPX8_RT.Instances
             InitializeTemperature();
             InitializePowerSuppliers();
             InitializeVpw();
+            InitializePlatingCells();
             InitializeReservoir();
             SystemFacilities systemFacilities = new SystemFacilities();
             AddCustomModuleDevice(systemFacilities);
@@ -126,6 +128,31 @@ namespace PunkHPX8_RT.Instances
             AddCustomDevice(vpwDeviceTimer);
         }
         /// <summary>
+        /// 初始化PlatingCell
+        /// </summary>
+        private void InitializePlatingCells()
+        {
+            foreach (string item in PlatingCellItemManager.Instance.InstalledModules)
+            {
+                PlatingCellItem platingCellItem = PlatingCellItemManager.Instance.GetPlatingCellItem(item);
+                if (platingCellItem.SubType == "DM")
+                {
+                    DMPlatingCellDevice platingCellDevice = new DMPlatingCellDevice(item);
+                    AddCustomDevice(platingCellDevice);
+                }
+                else if(platingCellItem.SubType == "HS")
+                {
+                    HSPlatingCellDevice platingCellDevice = new HSPlatingCellDevice(item);
+                    AddCustomDevice(platingCellDevice);
+                }
+                else
+                {
+                    DIPlatingCellDevice platingCellDevice = new DIPlatingCellDevice(item);
+                    AddCustomDevice(platingCellDevice);
+                }
+            }
+        }
+        /// <summary>
         /// 初始化Reservoir
         /// </summary>
         private void InitializeReservoir()

+ 20 - 0
PunkHPX8_RT/Devices/PlatingCell/DIPlatingCellDevice.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Devices.PlatingCell
+{
+    public class DIPlatingCellDevice:PlatingCellDevice
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="moduleName"></param>
+        public DIPlatingCellDevice(string moduleName) : base(moduleName)
+        {
+
+        }
+    }
+}

+ 21 - 0
PunkHPX8_RT/Devices/PlatingCell/DMPlatingCellDevice.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Devices.PlatingCell
+{
+    public class DMPlatingCellDevice : PlatingCellDevice
+    {
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="moduleName"></param>
+        public DMPlatingCellDevice(string moduleName) : base(moduleName)
+        {
+
+        }
+    }
+}

+ 20 - 0
PunkHPX8_RT/Devices/PlatingCell/HSPlatingCellDevice.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Devices.PlatingCell
+{
+    public class HSPlatingCellDevice : PlatingCellDevice
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="moduleName"></param>
+        public HSPlatingCellDevice(string moduleName) : base(moduleName)
+        {
+
+        }
+    }
+}

+ 444 - 0
PunkHPX8_RT/Devices/PlatingCell/PlatingCellDevice.cs

@@ -0,0 +1,444 @@
+using Aitex.Core.RT.DataCenter;
+using Aitex.Core.RT.Device;
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.OperationCenter;
+using Aitex.Core.Util;
+using MECF.Framework.Common.Persistent.Reservoirs;
+using MECF.Framework.Common.ToolLayout;
+using PunkHPX8_Core;
+using PunkHPX8_RT.Devices.LinMot;
+using PunkHPX8_RT.Devices.PowerSupplier;
+using PunkHPX8_RT.Modules;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Devices.PlatingCell
+{
+    public class PlatingCellDevice : BaseDevice, IDevice
+    {
+        #region 常量 
+        private const string PERSISTENT_VALUE = "PersistentValue";
+        private const string AUTO = "Auto";
+        private const string MANUAL = "Manual";
+        private const string STRATUS = "Stratus";
+        private const string DISABLED = "Disabled";
+        #endregion
+
+        #region 内部变量
+        /// <summary>
+        /// 操作当前状态
+        /// </summary>
+        protected RState _status;
+        /// <summary>
+        /// 持久化数据
+        /// </summary>
+        protected PlatingCellPersistentValue _persistentValue;
+        /// <summary>
+        /// A面PowerSupplier
+        /// </summary>
+        protected CellPowerSupplier _sideAPowerSupplier;
+        /// <summary>
+        /// B面PowerSupplier
+        /// </summary>
+        protected CellPowerSupplier _sideBPowerSupplier;
+        /// <summary>
+        /// Linmot
+        /// </summary>
+        protected LinMotAxis _linmotAxis;
+        /// <summary>
+        /// PlatingCell项
+        /// </summary>
+        private PlatingCellItem _platingCellItem;
+        #endregion
+
+        #region 属性
+        /// <summary>
+        /// 状态
+        /// </summary>
+        public RState Status { get { return _status; } }
+        /// <summary>
+        /// 是否禁用
+        /// </summary>
+        public bool IsDisable { get { return _persistentValue == null || _persistentValue.OperatingMode == DISABLED; } }
+       
+        /// <summary>
+        /// 操作模式
+        /// </summary>
+        public string OperationMode { get { return _persistentValue.OperatingMode; } }
+        /// <summary>
+        /// 工程模式
+        /// </summary>
+        public string EngineerMode { get { return _persistentValue.RecipeOperatingMode; } }
+        /// <summary>
+        /// A面PowerSupplier
+        /// </summary>
+        public CellPowerSupplier SideAPowerSupplier { get { return _sideAPowerSupplier; } }
+        /// <summary>
+        /// B面PowerSupplier
+        /// </summary>
+        public CellPowerSupplier SideBPowerSupplier { get { return _sideBPowerSupplier; } }
+        /// <summary>
+        /// 是否为Auto
+        /// </summary>
+        public bool IsAuto { get { return _persistentValue != null ? _persistentValue.OperatingMode == AUTO : false; } }
+        /// <summary>
+        /// 是否为Auto
+        /// </summary>
+        public bool IsManual { get { return _persistentValue != null ? _persistentValue.OperatingMode == MANUAL : false; } }
+        /// <summary>
+        /// linmot motor on 
+        /// </summary>
+        public bool IsLinmotMotorOn { get { return _linmotAxis != null ? _linmotAxis.IsMotorOn : false; } }
+
+        /// <summary>
+        /// Linmot当前位置
+        /// </summary>
+        public double LinmotPosition { get { return _linmotAxis != null ? _linmotAxis.CurrentPosition : 0; } }
+        #endregion
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="moduleName"></param>
+        public PlatingCellDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
+        {
+
+        }
+        /// <summary>
+        /// 初始化
+        /// </summary>
+        /// <returns></returns>
+        public virtual bool Initialize()
+        {
+            InitializeParameter();
+            SubscribeData();
+            InitializeOperation();
+            return true;
+        }
+        /// <summary>
+        /// 定时器执行
+        /// </summary>
+        public virtual bool OnTimer(int interval)
+        {
+            return true;
+        }
+
+        /// <summary>
+        /// 初始化参数
+        /// </summary>
+        private void InitializeParameter()
+        {
+            _persistentValue = PlatingCellPersistentManager.Instance.GetPlatingCellPersistentValue(Module);
+            if (_persistentValue == null)
+            {
+                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Persistent Value Object is not exist");
+            }
+            _platingCellItem = PlatingCellItemManager.Instance.GetPlatingCellItem(Module);
+            if (_platingCellItem != null)
+            {
+                _sideAPowerSupplier = DEVICE.GetDevice<CellPowerSupplier>(_platingCellItem.PlatingPowerSupplyAID);
+                _sideBPowerSupplier = DEVICE.GetDevice<CellPowerSupplier>(_platingCellItem.PlatingPowerSupplyBID);
+                _linmotAxis = DEVICE.GetDevice<LinMotAxis>(_platingCellItem.LinmotID);
+            }
+        }
+
+        /// <summary>
+        /// 订阅数据
+        /// </summary>
+        private void SubscribeData()
+        {
+            DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _persistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplierData", () => _sideAPowerSupplier.PowerSupplierData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplierData", () => _sideBPowerSupplier.PowerSupplierData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.ID", () => _sideAPowerSupplier.Module, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.IsConnected", () => _sideAPowerSupplier.IsConnected, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.Voltage", () => _sideAPowerSupplier.PowerSupplierData.Voltage, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.Current", () => _sideAPowerSupplier.PowerSupplierData.Current, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.SetPoint", () => _sideAPowerSupplier.PowerSupplierData.SetPoint, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.RunModel", () => _sideAPowerSupplier.PowerSupplierData.PowerRunModelContent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.PowerControl", () => _sideAPowerSupplier.PowerSupplierData.PowerControlContent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.PowerStatus", () => _sideAPowerSupplier.PowerSupplierData.PowerStatusContent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideAPowerSupplier.Enable", () => _sideBPowerSupplier.PowerSupplierData.Enabled, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.ID", () => _sideBPowerSupplier.Module, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.IsConnected", () => _sideAPowerSupplier.IsConnected, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.Voltage", () => _sideBPowerSupplier.PowerSupplierData.Voltage, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.Current", () => _sideBPowerSupplier.PowerSupplierData.Current, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.SetPoint", () => _sideBPowerSupplier.PowerSupplierData.SetPoint, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.RunModel", () => _sideBPowerSupplier.PowerSupplierData.PowerRunModelContent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.PowerControl", () => _sideBPowerSupplier.PowerSupplierData.PowerControlContent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.PowerStatus", () => _sideBPowerSupplier.PowerSupplierData.PowerStatusContent, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.SideBPowerSupplier.Enable", () => _sideBPowerSupplier.PowerSupplierData.Enabled, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.ID", () => _linmotAxis.Module, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.IsMotorOn", () => _linmotAxis.IsMotorOn, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.IsError", () => _linmotAxis.IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.IsSwitchOn", () => _linmotAxis.IsSwitchOn, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.CurveSpeed", () => _linmotAxis.CurveSpeed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.ErrorCode", () => _linmotAxis.ErrorCode, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.Linmot.CurrentPosition", () => _linmotAxis.CurrentPosition, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+        }
+        /// <summary>
+        /// 初始化操作
+        /// </summary>
+        protected virtual void InitializeOperation()
+        {
+            OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
+            OP.Subscribe($"{Module}.ManualAction", ManualOperation);
+            OP.Subscribe($"{Module}.AutoAction", AutoOperation);
+            OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
+            OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
+            OP.Subscribe($"{Module}.SetPlatingCellWaferSize", (cmd, args) => { return SetPlatingCellWaferSize(cmd, args); });
+        }
+        /// <summary>
+        /// 开始Curve
+        /// </summary>
+        /// <param name="speed"></param>
+        /// <returns></returns>
+        public bool StartCurveMotion(int speed)
+        {
+            if (_linmotAxis != null)
+            {
+                return _linmotAxis.StartCurve(speed);
+            }
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_METAL, Module, "linmot is null");
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 开始Curve
+        /// </summary>
+        /// <param name="speed"></param>
+        /// <returns></returns>
+        public bool ChangeCurveSpeedMotion(int speed)
+        {
+            if (_linmotAxis != null)
+            {
+                return _linmotAxis.ChangeCurveSpeed(speed);
+            }
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_METAL, Module, "linmot is null");
+                return false;
+            }
+        }
+        /// <summary>
+        /// ResetLinmot
+        /// </summary>
+        /// <returns></returns>
+        public bool ResetLinmot()
+        {
+            if (_linmotAxis != null)
+            {
+                return _linmotAxis.ResetOperation("", false);
+            }
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_METAL, Module, "linmot is null");
+                return false;
+            }
+        }
+        /// <summary>
+        /// 检验Linmot Routine状态是否为结束状态
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckLinmotRoutineEnd()
+        {
+            if (_linmotAxis != null)
+            {
+                return _linmotAxis.Status == RState.End;
+            }
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_METAL, Module, "linmot is null");
+                return false;
+            }
+        }
+        /// <summary>
+        /// 检验Linmot Routine状态是否为错误状态
+        /// </summary>
+        /// <returns></returns>
+        public bool CheckLinmotRoutineError()
+        {
+            if (_linmotAxis != null)
+            {
+                return _linmotAxis.Status == RState.Failed || _linmotAxis.Status == RState.Timeout;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        /// <summary>
+        /// 停止Linmot
+        /// </summary>
+        /// <returns></returns>
+        public bool StopLinmot()
+        {
+            if (_linmotAxis != null)
+            {
+                return _linmotAxis.StopOperation("", null);
+            }
+            else
+            {
+                LOG.WriteLog(eEvent.ERR_METAL, Module, "linmot is null");
+                return false;
+            }
+        }
+
+        #region Operation
+        /// <summary>
+        /// DisabledAction
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        public bool DisabledOperation(string cmd, object[] args)
+        {
+            //string currentOperation = "Disabled";
+            //MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
+            //if (metalEntity != null && _persistentValue != null && _persistentValue.OperatingMode != currentOperation)
+            //{
+            //    string preOperation = _persistentValue.OperatingMode;
+            //    if (metalEntity.IsBusy)
+            //    {
+            //        LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} is Busy, can't switch to Disabled mode");
+            //        return false;
+            //    }
+            //    if (SchedulerMetalTimeManager.Instance.Contained(Module))
+            //    {
+            //        LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} is in scheduler, can't switch to Disabled mode");
+            //        return false;
+            //    }
+            //    metalEntity.EnterInit();
+            //    _persistentValue.OperatingMode = currentOperation;
+
+            //    LOG.WriteLog(eEvent.INFO_METAL, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
+            //}
+
+            //MetalPersistentManager.Instance.UpdatePersistentValue(Module);
+            return true;
+        }
+        /// <summary>
+        /// ManualAction
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        public bool ManualOperation(string cmd, object[] args)
+        {
+            //string currentOperation = "Manual";
+            //MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
+            //if (metalEntity != null && _persistentValue != null && _persistentValue.OperatingMode != currentOperation)
+            //{
+            //    string preOperation = _persistentValue.OperatingMode;
+            //    if (metalEntity.IsBusy)
+            //    {
+            //        LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} is Busy, can't switch to Manual mode");
+            //        return false;
+            //    }
+            //    if (SchedulerMetalTimeManager.Instance.Contained(Module))
+            //    {
+            //        LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} is in scheduler, can't switch to Manual mode");
+            //        return false;
+            //    }
+            //    metalEntity.EnterInit();
+            //    _persistentValue.OperatingMode = currentOperation;
+
+            //    LOG.WriteLog(eEvent.INFO_METAL, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
+            //}
+
+            //MetalPersistentManager.Instance.UpdatePersistentValue(Module);
+            return true;
+        }
+        /// <summary>
+        /// AutoAction
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        public bool AutoOperation(string cmd, object[] args)
+        {
+            //string currentOperation = "Auto";
+            //MetalEntity metalEntity = Singleton<RouteManager>.Instance.GetModule<MetalEntity>(Module);
+            //if (metalEntity != null && _persistentValue != null && _persistentValue.OperatingMode != currentOperation)
+            //{
+            //    string preOperation = _persistentValue.OperatingMode;
+            //    if (metalEntity.IsBusy)
+            //    {
+            //        LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} is Busy, can't switch to Auto mode");
+            //        return false;
+            //    }
+            //    metalEntity.EnterInit();
+            //    _persistentValue.OperatingMode = currentOperation;
+
+            //    LOG.WriteLog(eEvent.INFO_METAL, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
+            //}
+
+            //MetalPersistentManager.Instance.UpdatePersistentValue(Module);
+            return true;
+        }
+        /// <summary>
+        /// EngineeringModeAction
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        private bool EngineeringModeOperation(string cmd, object[] args)
+        {
+            string currentRecipeOperation = "Engineering";
+            if (_persistentValue != null)
+            {
+                _persistentValue.RecipeOperatingMode = currentRecipeOperation;
+            }
+            PlatingCellPersistentManager.Instance.UpdatePersistentValue(Module);
+            return true;
+        }
+        /// <summary>
+        /// ProductionAction
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <param name="param"></param>
+        /// <returns></returns>
+        private bool ProductionModeOperation(string cmd, object[] args)
+        {
+            string currentRecipeOperation = "Production";
+            if (_persistentValue != null)
+            {
+                _persistentValue.RecipeOperatingMode = currentRecipeOperation;
+            }
+            PlatingCellPersistentManager.Instance.UpdatePersistentValue(Module);
+            return true;
+        }
+
+        private bool SetPlatingCellWaferSize(string cmd, object[] args)
+        {
+            string metalWaferSize = args[0] as string;
+            if (_persistentValue != null)
+            {
+                _persistentValue.PlatingCellWaferSize = int.Parse(metalWaferSize);
+            }
+            PlatingCellPersistentManager.Instance.UpdatePersistentValue(Module);
+            return true;
+        }
+        #endregion
+
+
+        
+
+        public virtual void Monitor()
+        {
+        }
+
+        public virtual void Reset()
+        {
+        }
+
+        public virtual void Terminate()
+        {
+        }
+    }
+}

+ 22 - 0
PunkHPX8_RT/Devices/Reservoir/ReservoirDevice.cs

@@ -32,6 +32,15 @@ namespace PunkHPX8_RT.Devices.Reservoir
 {
     public class ReservoirDevice : BaseDevice, IDevice
     {
+        private enum ReservoirOperation
+        {
+            None,
+            ManualANDiReplen,
+            ManualCADiReplen,
+            AutoANDiReplen,
+            AutoCADiReplen
+        }
+        
         #region 常量
         protected const string AUTO = "Auto";
         protected const string MANUAL = "Manual";
@@ -118,6 +127,11 @@ namespace PunkHPX8_RT.Devices.Reservoir
         /// 注水Helper
         /// </summary>
         private ReservoirDiReplenHelper _direplenHelper;
+        
+        /// <summary>
+        /// 当前操作
+        /// </summary>
+        private ReservoirOperation _currentOperation;
         #endregion
 
         #region Trigger
@@ -242,6 +256,11 @@ namespace PunkHPX8_RT.Devices.Reservoir
             DATA.Subscribe($"{Module}.CurrentRecipe", () => _resRecipe, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.IsCAHighLevel", () => IsCAHighLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
             DATA.Subscribe($"{Module}.IsCALowLevel", () => IsCALowLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+
+            DATA.Subscribe($"{Module}.DIValveMaxOnTime", () => SC.GetValue<double>($"Reservoir.{Module}.DIValveMaxOnTime") * 60, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsManualCAReplen", () => { return _currentOperation == ReservoirOperation.ManualCADiReplen; }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsDIReplenPerfillTimeOut", () => _isDIReplenPerfillTimeOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);
+            DATA.Subscribe($"{Module}.IsDIReplenMaxTimeOut", () => _isDIReplenMaxTimeOut, SubscriptionAttribute.FLAG.IgnoreSaveDB);
         }
         /// <summary>
         /// 初始化Operation
@@ -273,6 +292,9 @@ namespace PunkHPX8_RT.Devices.Reservoir
             OP.Subscribe($"{Module}.PhValveOff", (cmd, para) => { return PhValveOff(); });
             OP.Subscribe($"{Module}.HedValveOn", (cmd, para) => { return HedValveOn(); });
             OP.Subscribe($"{Module}.HedValveOff", (cmd, para) => { return HedValveOff(); });
+
+            OP.Subscribe($"{Module}.ResetTotalTime", ResetTotalTime);
+            OP.Subscribe($"{Module}.ManualCADiReplen", ManualCADiReplen);
         }
         /// <summary>
         /// 订阅变量数值发生变化

+ 59 - 0
PunkHPX8_RT/Modules/Reservoir/DIReservoirInitializeRoutine.cs

@@ -0,0 +1,59 @@
+using Aitex.Core.RT.Device;
+using Aitex.Core.RT.Routine;
+using Aitex.Core.RT.SCCore;
+using MECF.Framework.Common.Routine;
+using PunkHPX8_Core;
+using PunkHPX8_RT.Devices.PlatingCell;
+using PunkHPX8_RT.Devices.Reservoir;
+using PunkHPX8_RT.Devices.Temperature;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Modules.Reservoir
+{
+    public class DIReservoirInitializeRoutine : RoutineBase, IRoutine
+    {
+
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="module"></param>
+        public DIReservoirInitializeRoutine(string module) : base(module)
+        {
+        }
+
+        /// <summary>
+        /// 启动
+        /// </summary>
+        /// <param name="objs"></param>
+        /// <returns></returns>
+        public RState Start(params object[] objs)
+        {
+       
+            return RState.End;
+        }
+
+        /// <summary>
+        /// 监控
+        /// </summary>
+        /// <returns></returns>
+        public RState Monitor()
+        {
+
+            return RState.End;
+        }
+
+        /// <summary>
+        /// 中止
+        /// </summary>
+        public void Abort()
+        {
+
+        }
+    }
+}

+ 362 - 0
PunkHPX8_RT/Modules/Reservoir/DMReservoirInitializeRoutine.cs

@@ -0,0 +1,362 @@
+using Aitex.Core.RT.Device;
+using Aitex.Core.RT.Log;
+using Aitex.Core.RT.Routine;
+using Aitex.Core.RT.SCCore;
+using MECF.Framework.Common.Alarm;
+using MECF.Framework.Common.RecipeCenter;
+using MECF.Framework.Common.Routine;
+using MECF.Framework.Common.Utilities;
+using PunkHPX8_Core;
+using PunkHPX8_RT.Devices.Facilities;
+using PunkHPX8_RT.Devices.PlatingCell;
+using PunkHPX8_RT.Devices.Reservoir;
+using PunkHPX8_RT.Devices.Temperature;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Modules.Reservoir
+{
+    public class DMReservoirInitializeRoutine : RoutineBase, IRoutine
+    {
+        private enum InitializeStep
+        {
+            AutoDiReplen,
+            CAPump,
+            CAPumpWait,
+            ANPump,
+            ANPumpWait,
+            ManualCellDisableHED,
+            AutoCellAutoEnableHED,
+            AutoCellAutoEnableHEDDelay,
+            AutoCellAutoEnableHEDCheck,
+            AutoCellAutoCheckPowerSupplier,
+            AutoCellAutoLinmotReset,
+            AutoCellAutoLinmotResetCheck,
+            CellWSUnclamp,
+            AutoCloseBypass,
+            End
+        }
+        #region 常量 
+        private const string AUTO = "Auto";
+        private const string MANUAL = "Manual";
+        private const int ENABLE = 5;
+        #endregion
+        #region 内部变量
+        CAPumpOnRoutine _caPumpOnRoutine;
+        ANPumpOnRoutine _anPumpOnRoutine;
+        DMReservoirDevice _dmReservoirDevice;
+        private ResRecipe _recipe;
+        private PlatingCellDevice _platingCellDevices;
+        private TemperatureController _temperatureController;
+        private double _hedFlowLowLimit;
+        private int _autoHedDelay = 0;
+        #endregion
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="module"></param>
+        public DMReservoirInitializeRoutine(string module) : base(module)
+        {
+        }
+
+        /// <summary>
+        /// 中止
+        /// </summary>
+        public void Abort()
+        {
+            _caPumpOnRoutine.Abort();
+            _anPumpOnRoutine.Abort();
+        }
+        /// <summary>
+        /// 监控
+        /// </summary>
+        /// <returns></returns>
+        public RState Monitor()
+        {
+            Runner.RunIf(InitializeStep.AutoDiReplen, _recipe.DIReplenEnable || _recipe.ANDIReplenEnable, CheckFacilitiesDiReplenStatus, _delay_1ms)
+                .Run(InitializeStep.CAPump, () => { return _caPumpOnRoutine.Start() == RState.Running; }, _delay_1s)
+               .WaitWithStopCondition(InitializeStep.CAPumpWait, () => CommonFunction.CheckRoutineEndState(_caPumpOnRoutine), () => CommonFunction.CheckRoutineStopState(_caPumpOnRoutine))
+               .Run(InitializeStep.ANPump, () => { return _anPumpOnRoutine.Start() == RState.Running; }, _delay_1ms)
+               .WaitWithStopCondition(InitializeStep.ANPumpWait, () => CommonFunction.CheckRoutineEndState(_anPumpOnRoutine), () => CommonFunction.CheckRoutineStopState(_anPumpOnRoutine))
+                //Manual cell Bypass同时Enable HED
+                .Run(InitializeStep.AutoCellAutoEnableHED, AutoHedOn, _delay_1ms)
+                .Delay(InitializeStep.AutoCellAutoEnableHEDDelay, _autoHedDelay)
+                .Run(InitializeStep.AutoCellAutoEnableHEDCheck, AutoHedSuccess, _delay_1ms)
+                //检验PowerSupplier通信
+                .Run(InitializeStep.AutoCellAutoCheckPowerSupplier, AutoMetalsPowerSupplierCommuncationStatus, _delay_1ms)
+                //Cell Linmot Reset
+               
+                .WaitWithStopCondition(InitializeStep.AutoCellAutoLinmotResetCheck, CheckAutoMetalResetStatus, CheckAutoMetalResetStopStatus)
+                //Cell Unclamp
+                .Run(InitializeStep.CellWSUnclamp, MetalsWHUnclampOn, _delay_1ms)
+   
+                .End(InitializeStep.End, ClearAlarmDataError, _delay_1ms);
+            return Runner.Status;
+        }
+        /// <summary>
+        /// 检验总Di有没有开
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckFacilitiesDiReplenStatus()
+        {
+            SystemFacilities systemFacilities = DEVICE.GetDevice<SystemFacilities>("System.Facilities");
+            if (systemFacilities != null)
+            {
+                bool result = systemFacilities.DIReplenEnable;
+                if (!result)
+                {
+                    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Facilities DiReplen is disable");
+                }
+                return result;
+            }
+            return false;
+        }
+        /// <summary>
+        /// 启用HED
+        /// </summary>
+        /// <returns></returns>
+        private bool EnableHED()
+        {
+            return _temperatureController.EnableOperation("", null);
+        }
+        /// <summary>
+        /// 检验所有Metal处于Manual
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckAutoAndAllMetalAuto()
+        {
+            //if (_reservoirDevice.OperationMode != AUTO)
+            //{
+            //    return false;
+            //}
+            //for (int i = 0; i < _metalDevices.Count; i++)
+            //{
+            //    CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
+            //    if (hotMetalDevice.OperationMode != AUTO)
+            //    {
+            //        return false;
+            //    }
+            //}
+            return true;
+        }
+        /// <summary>
+        /// 自动HED On
+        /// </summary>
+        /// <returns></returns>
+        private bool AutoHedOn()
+        {
+            //double hedFlow = _dmReservoirDevice.ReservoirData.CAHedFlow;
+            //bool result = hedFlow > _hedFlowLowLimit;
+            //if (!result)
+            //{
+            //    LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"HED Flow {hedFlow} is less than {_hedFlowLowLimit}");
+            //    return false;
+            //}
+            //_autoHedDelay = _delay_2s;
+            //_temperatureController.EnableOperation("", null);
+            //_temperatureController.SetTargetTemperatureOperation("", new object[] { _recipe.TemperatureSetPoint });
+            return true;
+        }
+        /// <summary>
+        /// 检验Hed是否成功
+        /// </summary>
+        /// <returns></returns>
+        private bool AutoHedSuccess()
+        {
+            if (_temperatureController.TemperatureData.ControlOperationModel == 0)
+            {
+                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Temperature control is disable");
+                return false;
+            }
+            if (Math.Abs(_recipe.TemperatureSetPoint - _temperatureController.TemperatureData.TargetTemperature) >= 0.1 * _recipe.TemperatureSetPoint)
+            {
+                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"recipe temperature {_recipe.TemperatureSetPoint} is not match temperature target point {_temperatureController.TemperatureData.TargetTemperature}");
+                return false;
+            }
+            return true;
+        }
+        /// <summary>
+        /// 检验Metal A/B PowerSupplier通信状态
+        /// </summary>
+        /// <returns></returns>
+        private bool AutoMetalsPowerSupplierCommuncationStatus()
+        {
+            //for (int i = 0; i < _metalDevices.Count; i++)
+            //{
+            //    CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
+            //    if (hotMetalDevice.IsAuto)
+            //    {
+            //        if (hotMetalDevice.SideAPowerSupplier == null)
+            //        {
+            //            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Side A PowerSupplier is null");
+            //            return false;
+            //        }
+            //        if (hotMetalDevice.SideBPowerSupplier == null)
+            //        {
+            //            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Side B PowerSupplier is null");
+            //            return false;
+            //        }
+            //        if (!hotMetalDevice.SideAPowerSupplier.IsConnected)
+            //        {
+            //            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Side A PowerSupplier {hotMetalDevice.SideAPowerSupplier.Name} is not connected");
+            //            return false;
+            //        }
+            //        if (!hotMetalDevice.SideBPowerSupplier.IsConnected)
+            //        {
+            //            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, $"Side B PowerSupplier {hotMetalDevice.SideBPowerSupplier.Name} is not connected");
+            //            return false;
+            //        }
+            //    }
+            //}
+            return true;
+        }
+        /// <summary>
+        /// Auto Metal reset linmot
+        /// </summary>
+        /// <returns></returns>
+        private bool AutoMetalResetLinmot()
+        {
+            //for (int i = 0; i < _metalDevices.Count; i++)
+            //{
+            //    CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
+
+            //    if (hotMetalDevice.OperationMode == AUTO)
+            //    {
+            //        bool result = hotMetalDevice.ResetLinmot();
+            //        if (!result)
+            //        {
+            //            LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Reset linmot error");
+            //            return false;
+            //        }
+            //    }
+            //}
+            return true;
+        }
+        /// <summary>
+        /// Auto Metal reset linmot
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckAutoMetalResetStatus()
+        {
+            //if (_reservoirDevice.OperationMode == MANUAL)
+            //{
+            //    return true;
+            //}
+            //for (int i = 0; i < _metalDevices.Count; i++)
+            //{
+            //    CompactMembranMetalDevice metalDevice = _metalDevices[i];
+
+            //    if (metalDevice.OperationMode == AUTO)
+            //    {
+            //        bool result = metalDevice.CheckLinmotRoutineEnd();
+            //        if (!result)
+            //        {
+            //            return false;
+            //        }
+            //    }
+            //}
+            return true;
+        }
+
+
+        /// <summary>
+        /// Auto Metal reset linmot
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckAutoMetalResetStopStatus()
+        {
+            //if (_reservoirDevice.OperationMode == MANUAL)
+            //{
+            //    return false;
+            //}
+            //for (int i = 0; i < _metalDevices.Count; i++)
+            //{
+            //    CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
+
+            //    if (hotMetalDevice.OperationMode == AUTO)
+            //    {
+            //        bool result = hotMetalDevice.CheckLinmotRoutineError();
+            //        if (result)
+            //        {
+            //            return true;
+            //        }
+            //    }
+            //}
+            return false;
+        }
+        /// Metal WS Unclamp
+        /// </summary>
+        /// <returns></returns>
+        private bool MetalsWHUnclampOn()
+        {
+            //for (int i = 0; i < _metalDevices.Count; i++)
+            //{
+            //    CompactMembranMetalDevice hotMetalDevice = _metalDevices[i];
+            //    if (hotMetalDevice != null && !hotMetalDevice.IsDisable)
+            //    {
+            //        bool result = hotMetalDevice.WaferHolderUnclampOn("", null);
+            //        if (!result)
+            //        {
+            //            return false;
+            //        }
+            //    }
+            //}
+            //_reservoirDevice.InitializeCrossDose(true);
+            return true;
+        }
+        /// <summary>
+        /// 清除alarm界面相关的dataerror
+        /// </summary>
+        private bool ClearAlarmDataError()
+        {
+            //AlarmListManager.Instance.RemoveDataError(Module);
+            //_dmReservoirDevice.ClearErrorLogSet(Module); //清除device里面的ErrorLogSet
+            return true;
+        }
+        /// <summary>
+        /// 启动
+        /// </summary>
+        /// <param name="objs"></param>
+        /// <returns></returns>
+        public RState Start(params object[] objs)
+        {
+            _caPumpOnRoutine = new CAPumpOnRoutine(Module);
+            _anPumpOnRoutine = new ANPumpOnRoutine(Module);
+            _dmReservoirDevice = DEVICE.GetDevice<DMReservoirDevice>(Module);
+            //_dmReservoirDevice.ClearErrorLogSet(Module);
+            _platingCellDevices = (PlatingCellDevice)objs[0];
+            
+            _temperatureController = (TemperatureController)objs[1];
+            _recipe = _dmReservoirDevice.Recipe;
+            _autoHedDelay = 0;
+            _hedFlowLowLimit = SC.GetValue<double>($"Reservoir.{Module}.HEDFlowLowLimit");
+            if (!CheckPreCondition())
+            {
+                return RState.Failed;
+            }
+            return Runner.Start(Module, "Start D&M Initialize");
+        }
+
+        /// <summary>
+        /// 检验前置条件
+        /// </summary>
+        /// <returns></returns>
+        private bool CheckPreCondition()
+        {
+            if (_recipe == null)
+            {
+                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "recipe is null");
+                return false;
+            }
+            if (!_temperatureController.IsConnected)
+            {
+                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module, "Temperature is not connected");
+                return false;
+            }
+            return true;
+        }
+    }
+}

+ 54 - 0
PunkHPX8_RT/Modules/Reservoir/HSReservoirInitializeRoutine.cs

@@ -0,0 +1,54 @@
+using Aitex.Core.RT.Routine;
+using MECF.Framework.Common.Routine;
+using PunkHPX8_Core;
+using PunkHPX8_RT.Devices.Reservoir;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_RT.Modules.Reservoir
+{
+    public class HSReservoirInitializeRoutine : RoutineBase, IRoutine
+    {
+
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="module"></param>
+        public HSReservoirInitializeRoutine(string module) : base(module)
+        {
+        }
+
+        /// <summary>
+        /// 启动
+        /// </summary>
+        /// <param name="objs"></param>
+        /// <returns></returns>
+        public RState Start(params object[] objs)
+        {
+
+            return RState.Running;
+        }
+     
+        /// <summary>
+        /// 监控
+        /// </summary>
+        /// <returns></returns>
+        public RState Monitor()
+        {
+            
+            return RState.End;
+        }
+
+        /// <summary>
+        /// 中止
+        /// </summary>
+        public void Abort()
+        {
+
+        }
+    }
+}

+ 81 - 9
PunkHPX8_RT/Modules/Reservoir/ReservoirEntity.cs

@@ -2,6 +2,7 @@
 using Aitex.Core.RT.Device;
 using Aitex.Core.RT.Fsm;
 using Aitex.Core.RT.Log;
+using Aitex.Core.RT.OperationCenter;
 using Aitex.Core.RT.RecipeCenter;
 using Aitex.Core.Util;
 using Aitex.Core.Utilities;
@@ -12,6 +13,7 @@ using MECF.Framework.Common.ProcessCell;
 using MECF.Framework.Common.RecipeCenter;
 using MECF.Framework.Common.ToolLayout;
 using PunkHPX8_Core;
+using PunkHPX8_RT.Devices.PlatingCell;
 using PunkHPX8_RT.Devices.PowerSupplier;
 using PunkHPX8_RT.Devices.Temperature;
 using System;
@@ -125,6 +127,18 @@ namespace PunkHPX8_RT.Modules.Reservoir
         /// </summary>
         public ReservoirUsage ReservoirUsage { get { return ReservoirUsageManager.Instance.GetReservoirUsage(Module.ToString()); } }
         /// <summary>
+        /// dmPlatingCell device
+        /// </summary>
+        private DMPlatingCellDevice _dmPlatingCellDevice;
+        /// <summary>
+        /// hsPlatingCell device
+        /// </summary>
+        private HSPlatingCellDevice _hsPlatingCellDevice;
+        /// <summary>
+        /// diPlatingCell device
+        /// </summary>
+        private DIPlatingCellDevice _diPlatingCellDevice;
+        /// <summary>
         /// 温度控制设备
         /// </summary>
         private TemperatureController _temperatureController;
@@ -136,6 +150,18 @@ namespace PunkHPX8_RT.Modules.Reservoir
         /// 电源
         /// </summary>
         private CellPowerSupplier _powerSupplier;
+        /// <summary>
+        /// DM init routine
+        /// </summary>
+        private DMReservoirInitializeRoutine _dmInitializeRoutine;
+        /// <summary>
+        /// HS init routine
+        /// </summary>
+        private HSReservoirInitializeRoutine _hsInitializeRoutine;
+        /// <summary>
+        /// DI init routine
+        /// </summary>
+        private DIReservoirInitializeRoutine _diInitializeRoutine;
         #endregion
 
 
@@ -195,12 +221,17 @@ namespace PunkHPX8_RT.Modules.Reservoir
             _reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(Module.ToString());
             if (_reservoirItem != null)
             {
-                List<PlatingCellItem> platingCellItems = _reservoirItem.PlatingCells;
-                if (platingCellItems != null && platingCellItems.Count > 0)
+                if (_reservoirItem.SubType == "DM")
                 {
-                    foreach (PlatingCellItem platingCellItem in platingCellItems)
-                    { 
-                    }
+                   _dmPlatingCellDevice = DEVICE.GetDevice<DMPlatingCellDevice>(_reservoirItem.PlatingCells[0].ModuleName);
+                }
+                else if (_reservoirItem.SubType == "HS")
+                {
+                   _hsPlatingCellDevice = DEVICE.GetDevice<HSPlatingCellDevice>(_reservoirItem.PlatingCells[0].ModuleName);
+                }
+                else
+                {
+                   _diPlatingCellDevice = DEVICE.GetDevice<DIPlatingCellDevice>(_reservoirItem.PlatingCells[0].ModuleName);
                 }
                 if (!string.IsNullOrEmpty(_reservoirItem.CMMSupplyID))
                 {
@@ -218,7 +249,9 @@ namespace PunkHPX8_RT.Modules.Reservoir
         /// </summary>
         private void InitializeRoutine()
         {
-
+            _dmInitializeRoutine = new DMReservoirInitializeRoutine(Module.ToString());
+            _hsInitializeRoutine = new HSReservoirInitializeRoutine(Module.ToString());
+            _diInitializeRoutine = new DIReservoirInitializeRoutine(Module.ToString());
         }
         /// <summary>
         /// 初始化DATA
@@ -240,7 +273,7 @@ namespace PunkHPX8_RT.Modules.Reservoir
         /// </summary>
         private void InitializeOperation()
         {
-
+            OP.Subscribe($"{Module}.InitializeAll", (cmd, args) => { return CheckToPostMessage<ReservoirState, ReservoirMsg>(eEvent.ERR_RESERVOIR, Module.ToString(), (int)ReservoirMsg.Initialize); });
         }
 
         /// 初始化状态机
@@ -273,7 +306,28 @@ namespace PunkHPX8_RT.Modules.Reservoir
         /// <returns></returns>
         private bool InitializeAll(object[] param)
         {
-            return true;
+            
+            if (_persistentValue == null)
+            {
+                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "persistent is null");
+                return false;
+            }
+            //if (!ReservoirUsageMonitor(Module.ToString()))
+            //{
+            //    return false;
+            //}
+            if (_reservoirItem.SubType == "DM")
+            {
+                return _dmInitializeRoutine.Start(_dmPlatingCellDevice, _powerSupplier, _temperatureController) == RState.Running;
+            }
+            else if(_reservoirItem.SubType == "HS")
+            {
+                return _hsInitializeRoutine.Start(_hsPlatingCellDevice, _temperatureController) == RState.Running;
+            }
+            else
+            {
+                return _diInitializeRoutine.Start(_diPlatingCellDevice, _temperatureController) == RState.Running;
+            }
         }
         /// <summary>
         /// Initialize 监控
@@ -282,7 +336,25 @@ namespace PunkHPX8_RT.Modules.Reservoir
         /// <returns></returns>
         private bool InitializeAllMonitor(object[] param)
         {
-            return true;
+            RState ret = RState.Init;
+            if (_reservoirItem.SubType == "DM")
+            {
+                ret = _dmInitializeRoutine.Monitor();
+            }
+            else if(_reservoirItem.SubType == "HS")
+            {
+                ret = _hsInitializeRoutine.Monitor();
+            }
+            else
+            {
+                ret = _diInitializeRoutine.Monitor();
+            }
+            if (ret == RState.Failed || ret == RState.Timeout)
+            {
+                PostMsg(ReservoirMsg.Error);
+                return false;
+            }
+            return ret == RState.End;
         }
         #endregion