Browse Source

add vpw setup/motion view

chenzk 1 day ago
parent
commit
987e7728be
25 changed files with 2175 additions and 313 deletions
  1. 32 0
      PunkHPX8_MainPages/PunkHPX8_MainPages.csproj
  2. 57 57
      PunkHPX8_MainPages/ViewModels/PrewetHomePageViewModel.cs
  3. 192 192
      PunkHPX8_MainPages/ViewModels/StandardHotReservoirsViewModel.cs
  4. 14 0
      PunkHPX8_MainPages/ViewModels/VPWCellViewModel.cs
  5. 14 0
      PunkHPX8_MainPages/ViewModels/VPWMainViewModel.cs
  6. 193 0
      PunkHPX8_MainPages/ViewModels/VPWMotionViewModel.cs
  7. 208 0
      PunkHPX8_MainPages/ViewModels/VPWStationSetupViewModel.cs
  8. 15 0
      PunkHPX8_MainPages/Views/VPWCellView.xaml
  9. 28 0
      PunkHPX8_MainPages/Views/VPWCellView.xaml.cs
  10. 15 0
      PunkHPX8_MainPages/Views/VPWMainView.xaml
  11. 28 0
      PunkHPX8_MainPages/Views/VPWMainView.xaml.cs
  12. 34 0
      PunkHPX8_MainPages/Views/VPWMotionView.xaml
  13. 28 0
      PunkHPX8_MainPages/Views/VPWMotionView.xaml.cs
  14. 51 0
      PunkHPX8_MainPages/Views/VPWStationSetupView.xaml
  15. 28 0
      PunkHPX8_MainPages/Views/VPWStationSetupView.xaml.cs
  16. 28 0
      PunkHPX8_RT/Config/Devices/AxisProviderCfg.xml
  17. 11 4
      PunkHPX8_RT/Config/Layout/ToolLayoutConfiguration.xml
  18. 5 0
      PunkHPX8_RT/Devices/VpwCell/VpwCellDevice.cs
  19. 14 0
      PunkHPX8_Themes/PunkHPX8_Themes.csproj
  20. 239 0
      PunkHPX8_Themes/UserControls/VPWMotionControl.xaml
  21. 287 0
      PunkHPX8_Themes/UserControls/VPWMotionControl.xaml.cs
  22. 72 0
      PunkHPX8_Themes/UserControls/VPWStationPositionControl.xaml
  23. 425 0
      PunkHPX8_Themes/UserControls/VPWStationPositionControl.xaml.cs
  24. 45 42
      PunkHPX8_UI/Config/UIMenu.json
  25. 112 18
      PunkHPX8_UI/Config/UIMenu_permission.json

+ 32 - 0
PunkHPX8_MainPages/PunkHPX8_MainPages.csproj

@@ -217,6 +217,10 @@
     <Compile Include="ViewModels\SystemConfigViewModel.cs" />
     <Compile Include="ViewModels\TopViewModel.cs" />
     <Compile Include="ViewModels\VATPerformanceViewModel.cs" />
+    <Compile Include="ViewModels\VPWCellViewModel.cs" />
+    <Compile Include="ViewModels\VPWMainViewModel.cs" />
+    <Compile Include="ViewModels\VPWMotionViewModel.cs" />
+    <Compile Include="ViewModels\VPWStationSetupViewModel.cs" />
     <Compile Include="ViewModels\WaferDialogViewModel.cs" />
     <Compile Include="ViewModels\WaferHistoryDBViewModel.cs" />
     <Compile Include="Views\AlarmHomePageView.xaml.cs">
@@ -378,6 +382,18 @@
     <Compile Include="Views\VATPerformanceView.xaml.cs">
       <DependentUpon>VATPerformanceView.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Views\VPWCellView.xaml.cs">
+      <DependentUpon>VPWCellView.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Views\VPWMainView.xaml.cs">
+      <DependentUpon>VPWMainView.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Views\VPWMotionView.xaml.cs">
+      <DependentUpon>VPWMotionView.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Views\VPWStationSetupView.xaml.cs">
+      <DependentUpon>VPWStationSetupView.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Views\WaferAssociationUnit.xaml.cs">
       <DependentUpon>WaferAssociationUnit.xaml</DependentUpon>
     </Compile>
@@ -635,6 +651,22 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Views\VPWCellView.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Views\VPWMainView.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Views\VPWMotionView.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Views\VPWStationSetupView.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Views\WaferAssociationUnit.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>

+ 57 - 57
PunkHPX8_MainPages/ViewModels/PrewetHomePageViewModel.cs

@@ -479,63 +479,63 @@ namespace PunkHPX8_MainPages.ViewModels
         /// <param name="e"></param>
         private void Timer_Tick(object sender, EventArgs e)
         {
-            if (_rtDataKeys.Count != 0)
-            {
-                _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
-                if (_rtDataValueDic != null)
-                {
-                    PrewetPumpData = CommonFunction.GetValue<PrewetPumpData>(_rtDataValueDic, $"{Module}.{PUMP_DATA}");
-                    SeqRecipe = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.SequenceRecipe");
-                    AchievedRunRecipeCycle = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.AchievedCycle");
-                    //获取的是配置文件中keepwet开始的等待时间,后续倒计时实现在后端实现
-                    KeepWetLimitTime = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.GetKeepWetLimit");
-                    PrewetPersistent = CommonFunction.GetValue<PrewetPersistentValue>(_rtDataValueDic, $"{Module}.{PERSISTENT_VALUE}");
-                    State = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.FsmState");
-                    if ("Manual".Equals(PrewetPersistent.OperatingMode))
-                    {
-                        IsEnabled = true;
-                        IsAutoEnabled = true;
-                    }
-                    else if ("Auto".Equals(PrewetPersistent.OperatingMode))
-                    {
-                        IsAutoEnabled = true;
-                        IsEnabled = false;
-                    }
-                    else
-                    {
-                        State = "Stopped";
-                        IsEnabled = false;
-                        IsAutoEnabled = false;
-                    }
-                    StateMachine = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentStateMachine");
-                    Status = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentStatus");
-                    LinmotDeviceCommonData = CommonFunction.GetValue<LinMotDeviceData>(_rtDataValueDic, $"{Module}.LinmotDeviceData");
-                    UpMaxSpeed = LinmotDeviceCommonData.UpMaxSpeed / 1000;
-                    if(!string.IsNullOrEmpty(LinmotName))
-                    {
-                        ScanCount = CommonFunction.GetValue<int>(_rtDataValueDic, $"{LinmotName}.ScanCount");
-                        StatusWord = CommonFunction.GetValue<short>(_rtDataValueDic, $"{LinmotName}.StatusWord");
-                        LinmotCurrentPosition = CommonFunction.GetValue<double>(_rtDataValueDic, $"{LinmotName}.Position");
-                        UILinmotYPosition = CommonFunction.GetValue<double>(_rtDataValueDic, $"{LinmotName}.CurrentPrewetUIPostion");
-                    }
-                    //Error时UI腔体变红
-                    IsErrorState = "Error".Equals(State) ? true : false;
-                    //Recipe Running时Linmot完成完整Scan的计数
-                    ScanComplete = AchievedRunRecipeCycle * NumberOfRecipeScans + ScanCount;
-                    if ((StatusWord & 0b010000000000000) >> 13 != 1)  
-                    {
-                        ScanComplete -= ScanCount;
-                    }
-                    CurrentRecipe = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentRecipe");
-                    TotalTime = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.TotalTime");
-                    TimeRemaining = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.TimeRemain");
-                    TimeRemaining = TimeRemaining < 0 ? 0 : TimeRemaining;
-                    if (State == "Idle")
-                    {
-                        TimeRemaining = 0;
-                    }
-                }
-            }
+            //if (_rtDataKeys.Count != 0)
+            //{
+            //    _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
+            //    if (_rtDataValueDic != null)
+            //    {
+            //        PrewetPumpData = CommonFunction.GetValue<PrewetPumpData>(_rtDataValueDic, $"{Module}.{PUMP_DATA}");
+            //        SeqRecipe = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.SequenceRecipe");
+            //        AchievedRunRecipeCycle = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.AchievedCycle");
+            //        //获取的是配置文件中keepwet开始的等待时间,后续倒计时实现在后端实现
+            //        KeepWetLimitTime = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.GetKeepWetLimit");
+            //        PrewetPersistent = CommonFunction.GetValue<PrewetPersistentValue>(_rtDataValueDic, $"{Module}.{PERSISTENT_VALUE}");
+            //        State = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.FsmState");
+            //        if ("Manual".Equals(PrewetPersistent.OperatingMode))
+            //        {
+            //            IsEnabled = true;
+            //            IsAutoEnabled = true;
+            //        }
+            //        else if ("Auto".Equals(PrewetPersistent.OperatingMode))
+            //        {
+            //            IsAutoEnabled = true;
+            //            IsEnabled = false;
+            //        }
+            //        else
+            //        {
+            //            State = "Stopped";
+            //            IsEnabled = false;
+            //            IsAutoEnabled = false;
+            //        }
+            //        StateMachine = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentStateMachine");
+            //        Status = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentStatus");
+            //        LinmotDeviceCommonData = CommonFunction.GetValue<LinMotDeviceData>(_rtDataValueDic, $"{Module}.LinmotDeviceData");
+            //        UpMaxSpeed = LinmotDeviceCommonData.UpMaxSpeed / 1000;
+            //        if(!string.IsNullOrEmpty(LinmotName))
+            //        {
+            //            ScanCount = CommonFunction.GetValue<int>(_rtDataValueDic, $"{LinmotName}.ScanCount");
+            //            StatusWord = CommonFunction.GetValue<short>(_rtDataValueDic, $"{LinmotName}.StatusWord");
+            //            LinmotCurrentPosition = CommonFunction.GetValue<double>(_rtDataValueDic, $"{LinmotName}.Position");
+            //            UILinmotYPosition = CommonFunction.GetValue<double>(_rtDataValueDic, $"{LinmotName}.CurrentPrewetUIPostion");
+            //        }
+            //        //Error时UI腔体变红
+            //        IsErrorState = "Error".Equals(State) ? true : false;
+            //        //Recipe Running时Linmot完成完整Scan的计数
+            //        ScanComplete = AchievedRunRecipeCycle * NumberOfRecipeScans + ScanCount;
+            //        if ((StatusWord & 0b010000000000000) >> 13 != 1)  
+            //        {
+            //            ScanComplete -= ScanCount;
+            //        }
+            //        CurrentRecipe = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.CurrentRecipe");
+            //        TotalTime = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.TotalTime");
+            //        TimeRemaining = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.TimeRemain");
+            //        TimeRemaining = TimeRemaining < 0 ? 0 : TimeRemaining;
+            //        if (State == "Idle")
+            //        {
+            //            TimeRemaining = 0;
+            //        }
+            //    }
+            //}
         }
         /// <summary>
         /// 隐藏

+ 192 - 192
PunkHPX8_MainPages/ViewModels/StandardHotReservoirsViewModel.cs

@@ -750,35 +750,35 @@ namespace PunkHPX8_MainPages.ViewModels
             Module = systemName;
 
             _rtDataKeys.Clear();
-            _rtDataKeys.Add($"{Module}.Metals");
-            _rtDataKeys.Add($"{Module}.ReplenType");
-            Dictionary<string,object> tmpMetals = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
+            //_rtDataKeys.Add($"{Module}.Metals");
+            //_rtDataKeys.Add($"{Module}.ReplenType");
+            //Dictionary<string,object> tmpMetals = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
 
-            if (tmpMetals != null)
-            {
-                string replenType = CommonFunction.GetValue<string>(tmpMetals, $"{Module}.ReplenType");
-                IsDosingSystemEnabled = replenType != "" ? true : false;
-                List<string> strMetals = CommonFunction.GetValue<List<string>>(tmpMetals, $"{Module}.Metals");
-                CellsCount = strMetals.Count;
-                if(strMetals!=null&& CellsCount>= 1)
-                {
-                    CellModuleNameCollection.Clear();
-                    MetalDataCollection.Clear();
-                    CellModuleSignalPump.Clear();
-                    for (int i = 0; i < CellsCount; i++)
-                    {
-                        string metal=strMetals[i];
-                        if (!string.IsNullOrEmpty(metal))
-                        {
-                            CellModuleNameCollection.Add(metal);
-                            _rtDataKeys.Add($"{metal}.MetalData");
-                            _rtDataKeys.Add($"{metal}.IsSingalPump");
-                        }
-                        MetalDataCollection.Add(new StandardHotMetalDeviceData());
-                        CellModuleSignalPump.Add(false);
-                    }
-                }
-            }
+            //if (tmpMetals != null)
+            //{
+            //    string replenType = CommonFunction.GetValue<string>(tmpMetals, $"{Module}.ReplenType");
+            //    IsDosingSystemEnabled = replenType != "" ? true : false;
+            //    List<string> strMetals = CommonFunction.GetValue<List<string>>(tmpMetals, $"{Module}.Metals");
+            //    CellsCount = strMetals.Count;
+            //    if(strMetals!=null&& CellsCount>= 1)
+            //    {
+            //        CellModuleNameCollection.Clear();
+            //        MetalDataCollection.Clear();
+            //        CellModuleSignalPump.Clear();
+            //        for (int i = 0; i < CellsCount; i++)
+            //        {
+            //            string metal=strMetals[i];
+            //            if (!string.IsNullOrEmpty(metal))
+            //            {
+            //                CellModuleNameCollection.Add(metal);
+            //                _rtDataKeys.Add($"{metal}.MetalData");
+            //                _rtDataKeys.Add($"{metal}.IsSingalPump");
+            //            }
+            //            MetalDataCollection.Add(new StandardHotMetalDeviceData());
+            //            CellModuleSignalPump.Add(false);
+            //        }
+            //    }
+            //}
             _rtDataKeys.Add($"{Module}.ReservoirData");
             _rtDataKeys.Add($"{Module}.PersistentValue");
             _rtDataKeys.Add($"{Module}.IsManualReplen");
@@ -1005,178 +1005,178 @@ namespace PunkHPX8_MainPages.ViewModels
         /// <param name="e"></param>
         private void Timer_Tick(object sender, EventArgs e)
         {
-            if (_rtDataKeys.Count != 0)
-            {
-                _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
-                if (_rtDataValueDic != null)
-                {
-                    IsCMMConfig = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsCMMConfig");
-                    IsRegulatePump = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsRegulatePump");
-                    PumpSpeed = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.PumpSpeed");
-                    ReservoirsPersistent = CommonFunction.GetValue<ReservoirsPersistentValue>(_rtDataValueDic, $"{Module}.PersistentValue");
-                    IsManualReplen = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsManualReplen");
-                    DIValveMaxOnTime = CommonFunction.GetValue<double>(_rtDataValueDic, $"{Module}.DIValveMaxOnTime");
-                    CurrentRecipe = CommonFunction.GetValue<ResRecipe>(_rtDataValueDic, $"{Module}.CurrentRecipe");
-                    TemperatureControlData = CommonFunction.GetValue<TemperatureControllerData>(_rtDataValueDic, $"{Module}.TemperatureControllerData");
-                    TCEnableStatus = TemperatureControlData.ControlOperationModel == 0 ? "Disable" : "Enable";
-                    CmmPowerSupplierData = CommonFunction.GetValue<PowerSupplierData>(_rtDataValueDic, $"{Module}.CmmPowerSupplierData");
-                    State = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.FsmState");
-                    AvgLevel = CommonFunction.GetValue<double>(_rtDataValueDic, $"{Module}.ReservoirAverageLevel");
-                    ReservoirUsage reservoirUsage = CommonFunction.GetValue<ReservoirUsage>(_rtDataValueDic, $"{Module}.ReservoirUsage");
-                    if(reservoirUsage != null)
-                    {
-                        CMMAnodeUsage = reservoirUsage.CMMAnodeUsage;
-                        CMMCathodeUsage = reservoirUsage.CMMMembranceUsage;
-                        //CMM AnodeUsage
-                        if (CMMAnodeUsage > _cmmAnodeTotalAmpHoursFaultLimit)
-                        {
-                            IsCMMAnodeTotalAmpHoursFault = true;
-                            IsCMMAnodeTotalAmpHoursWarning = false;
-                        } 
-                        else if(CMMAnodeUsage > _cmmAnodeTotalAmpHoursWarningLimit)
-                        {
-                            IsCMMAnodeTotalAmpHoursWarning = true;
-                            IsCMMAnodeTotalAmpHoursFault = false;
-                        }
-                        else
-                        {
-                            IsCMMAnodeTotalAmpHoursWarning = false;
-                            IsCMMAnodeTotalAmpHoursFault = false;
-                        }
-                        //CMM CathodeUsage
-                        if (CMMCathodeUsage > _cmmCathodeTotalAmpHoursFaultLimit)
-                        {
-                            IsCMMCathodeTotalAmpHoursFault = true;
-                            IsCMMCathodeTotalAmpHoursWarning = false;
-                        }
-                        else if (CMMCathodeUsage > _cmmCathodeTotalAmpHoursWarningLimit)
-                        {
-                            IsCMMCathodeTotalAmpHoursWarning = true;
-                            IsCMMCathodeTotalAmpHoursFault = false;
-                        }
-                        else
-                        {
-                            IsCMMCathodeTotalAmpHoursWarning = false;
-                            IsCMMCathodeTotalAmpHoursFault = false;
-                        }
-                    }
+            //if (_rtDataKeys.Count != 0)
+            //{
+            //    _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
+            //    if (_rtDataValueDic != null)
+            //    {
+            //        IsCMMConfig = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsCMMConfig");
+            //        IsRegulatePump = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsRegulatePump");
+            //        PumpSpeed = CommonFunction.GetValue<int>(_rtDataValueDic, $"{Module}.PumpSpeed");
+            //        ReservoirsPersistent = CommonFunction.GetValue<ReservoirsPersistentValue>(_rtDataValueDic, $"{Module}.PersistentValue");
+            //        IsManualReplen = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsManualReplen");
+            //        DIValveMaxOnTime = CommonFunction.GetValue<double>(_rtDataValueDic, $"{Module}.DIValveMaxOnTime");
+            //        CurrentRecipe = CommonFunction.GetValue<ResRecipe>(_rtDataValueDic, $"{Module}.CurrentRecipe");
+            //        TemperatureControlData = CommonFunction.GetValue<TemperatureControllerData>(_rtDataValueDic, $"{Module}.TemperatureControllerData");
+            //        TCEnableStatus = TemperatureControlData.ControlOperationModel == 0 ? "Disable" : "Enable";
+            //        CmmPowerSupplierData = CommonFunction.GetValue<PowerSupplierData>(_rtDataValueDic, $"{Module}.CmmPowerSupplierData");
+            //        State = CommonFunction.GetValue<string>(_rtDataValueDic, $"{Module}.FsmState");
+            //        AvgLevel = CommonFunction.GetValue<double>(_rtDataValueDic, $"{Module}.ReservoirAverageLevel");
+            //        ReservoirUsage reservoirUsage = CommonFunction.GetValue<ReservoirUsage>(_rtDataValueDic, $"{Module}.ReservoirUsage");
+            //        if(reservoirUsage != null)
+            //        {
+            //            CMMAnodeUsage = reservoirUsage.CMMAnodeUsage;
+            //            CMMCathodeUsage = reservoirUsage.CMMMembranceUsage;
+            //            //CMM AnodeUsage
+            //            if (CMMAnodeUsage > _cmmAnodeTotalAmpHoursFaultLimit)
+            //            {
+            //                IsCMMAnodeTotalAmpHoursFault = true;
+            //                IsCMMAnodeTotalAmpHoursWarning = false;
+            //            } 
+            //            else if(CMMAnodeUsage > _cmmAnodeTotalAmpHoursWarningLimit)
+            //            {
+            //                IsCMMAnodeTotalAmpHoursWarning = true;
+            //                IsCMMAnodeTotalAmpHoursFault = false;
+            //            }
+            //            else
+            //            {
+            //                IsCMMAnodeTotalAmpHoursWarning = false;
+            //                IsCMMAnodeTotalAmpHoursFault = false;
+            //            }
+            //            //CMM CathodeUsage
+            //            if (CMMCathodeUsage > _cmmCathodeTotalAmpHoursFaultLimit)
+            //            {
+            //                IsCMMCathodeTotalAmpHoursFault = true;
+            //                IsCMMCathodeTotalAmpHoursWarning = false;
+            //            }
+            //            else if (CMMCathodeUsage > _cmmCathodeTotalAmpHoursWarningLimit)
+            //            {
+            //                IsCMMCathodeTotalAmpHoursWarning = true;
+            //                IsCMMCathodeTotalAmpHoursFault = false;
+            //            }
+            //            else
+            //            {
+            //                IsCMMCathodeTotalAmpHoursWarning = false;
+            //                IsCMMCathodeTotalAmpHoursFault = false;
+            //            }
+            //        }
 
 
-                    if ("Manual".Equals(ReservoirsPersistent.OperatingMode))
-                    {
-                        IsEnabled = true;
-                        IsAutoEnabled = true;
-                    }
-                    else if ("Auto".Equals(ReservoirsPersistent.OperatingMode))
-                    {
-                        IsAutoEnabled = true;
-                        IsEnabled = false;
-                    }
-                    else
-                    {
-                        State = "Stopped";
-                        IsEnabled = false;
-                        IsAutoEnabled = false;
-                    }
-                    for (int i = 0;i < CellsCount;i++)
-                    {
-                        MetalDataCollection[i] = CommonFunction.GetValue<StandardHotMetalDeviceData>(_rtDataValueDic, $"{CellModuleNameCollection[i]}.MetalData");
+            //        if ("Manual".Equals(ReservoirsPersistent.OperatingMode))
+            //        {
+            //            IsEnabled = true;
+            //            IsAutoEnabled = true;
+            //        }
+            //        else if ("Auto".Equals(ReservoirsPersistent.OperatingMode))
+            //        {
+            //            IsAutoEnabled = true;
+            //            IsEnabled = false;
+            //        }
+            //        else
+            //        {
+            //            State = "Stopped";
+            //            IsEnabled = false;
+            //            IsAutoEnabled = false;
+            //        }
+            //        for (int i = 0;i < CellsCount;i++)
+            //        {
+            //            MetalDataCollection[i] = CommonFunction.GetValue<StandardHotMetalDeviceData>(_rtDataValueDic, $"{CellModuleNameCollection[i]}.MetalData");
                        
-                        CellModuleSignalPump[i] = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{CellModuleNameCollection[i]}.IsSingalPump");
-                    }
-                    ReservoirData = CommonFunction.GetValue<StandardHotReservoirData>(_rtDataValueDic, $"{Module}.ReservoirData");
-                    if (ReservoirData != null) 
-                    {
-                        for (int i = 0; i < CellsCount; i++)
-                        {
-                            MetalDataCollection[i].CellPump ^= ReservoirData.RegulatePumpSignalIn; //确保管路开关正常显示
-                        }  
-                    }
-                    if (CurrentRecipe != null)
-                    {
-                        //PHLow报警灯
-                        IsPHLowLimit = (ReservoirData != null && ReservoirData.PHValue < CurrentRecipe.PHErrorLow) ? true : false;
-                        //PHHigh报警灯
-                        IsPHHighLimit = (ReservoirData != null && ReservoirData.PHValue > CurrentRecipe.PHErrorHigh) ? true : false;
-                        if(CmmPowerSupplierData != null)
-                        {
-                            //PowerSupply High报警灯
-                            if (CmmPowerSupplierData.Current <= CurrentRecipe.CMMCurrentSetPoint * (1 + (double)CurrentRecipe.CMMCurrentWarningPercent/100))
-                            {
-                                CurrentHighStatus = "Normal";
-                            }
-                            else if (CmmPowerSupplierData.Current > CurrentRecipe.CMMCurrentSetPoint * (1 + (double)CurrentRecipe.CMMCurrentFaultPercent/100))
-                            {
-                                CurrentHighStatus = "Error";
-                            }
-                            else
-                            {
-                                CurrentHighStatus = "Warning";
-                            }
-                            //PowerSupply Low报警灯
-                            if (CmmPowerSupplierData.Current >= CurrentRecipe.CMMCurrentSetPoint * (1 - (double)CurrentRecipe.CMMCurrentWarningPercent/100))
-                            {
-                                CurrentLowStatus = "Normal";
-                            }
-                            else if (CmmPowerSupplierData.Current < CurrentRecipe.CMMCurrentSetPoint * (1 - (double)CurrentRecipe.CMMCurrentFaultPercent/100))
-                            {
-                                CurrentLowStatus = "Error";
-                            }
-                            else
-                            {
-                                CurrentLowStatus = "Warning";
-                            }
-                            IsBelowMinVoltage = CmmPowerSupplierData.Voltage < CurrentRecipe.CMMMinVoltage ? true : false;
-                        }
+            //            CellModuleSignalPump[i] = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{CellModuleNameCollection[i]}.IsSingalPump");
+            //        }
+            //        ReservoirData = CommonFunction.GetValue<StandardHotReservoirData>(_rtDataValueDic, $"{Module}.ReservoirData");
+            //        if (ReservoirData != null) 
+            //        {
+            //            for (int i = 0; i < CellsCount; i++)
+            //            {
+            //                MetalDataCollection[i].CellPump ^= ReservoirData.RegulatePumpSignalIn; //确保管路开关正常显示
+            //            }  
+            //        }
+            //        if (CurrentRecipe != null)
+            //        {
+            //            //PHLow报警灯
+            //            IsPHLowLimit = (ReservoirData != null && ReservoirData.PHValue < CurrentRecipe.PHErrorLow) ? true : false;
+            //            //PHHigh报警灯
+            //            IsPHHighLimit = (ReservoirData != null && ReservoirData.PHValue > CurrentRecipe.PHErrorHigh) ? true : false;
+            //            if(CmmPowerSupplierData != null)
+            //            {
+            //                //PowerSupply High报警灯
+            //                if (CmmPowerSupplierData.Current <= CurrentRecipe.CMMCurrentSetPoint * (1 + (double)CurrentRecipe.CMMCurrentWarningPercent/100))
+            //                {
+            //                    CurrentHighStatus = "Normal";
+            //                }
+            //                else if (CmmPowerSupplierData.Current > CurrentRecipe.CMMCurrentSetPoint * (1 + (double)CurrentRecipe.CMMCurrentFaultPercent/100))
+            //                {
+            //                    CurrentHighStatus = "Error";
+            //                }
+            //                else
+            //                {
+            //                    CurrentHighStatus = "Warning";
+            //                }
+            //                //PowerSupply Low报警灯
+            //                if (CmmPowerSupplierData.Current >= CurrentRecipe.CMMCurrentSetPoint * (1 - (double)CurrentRecipe.CMMCurrentWarningPercent/100))
+            //                {
+            //                    CurrentLowStatus = "Normal";
+            //                }
+            //                else if (CmmPowerSupplierData.Current < CurrentRecipe.CMMCurrentSetPoint * (1 - (double)CurrentRecipe.CMMCurrentFaultPercent/100))
+            //                {
+            //                    CurrentLowStatus = "Error";
+            //                }
+            //                else
+            //                {
+            //                    CurrentLowStatus = "Warning";
+            //                }
+            //                IsBelowMinVoltage = CmmPowerSupplierData.Voltage < CurrentRecipe.CMMMinVoltage ? true : false;
+            //            }
                         
-                    }
-                    if (ReservoirData != null)
-                    {
-                        //CMM Flow High报警灯
-                        if (ReservoirData.Flow <= _reservoirCMMFlowHighWarning)
-                        {
-                            FlowHighStatus = "Normal";
+            //        }
+            //        if (ReservoirData != null)
+            //        {
+            //            //CMM Flow High报警灯
+            //            if (ReservoirData.Flow <= _reservoirCMMFlowHighWarning)
+            //            {
+            //                FlowHighStatus = "Normal";
 
-                        }
-                        else if (ReservoirData.Flow > _reservoirCMMFlowHighError)
-                        {
-                            FlowHighStatus = "Error";
-                        }
-                        else
-                        {
-                            FlowHighStatus = "Warning";
-                        }
-                        //CMM Flow Low报警灯
-                        if (ReservoirData.Flow >= _reservoirCMMFlowLowWarning)
-                        {
-                            FlowLowStatus = "Normal";
+            //            }
+            //            else if (ReservoirData.Flow > _reservoirCMMFlowHighError)
+            //            {
+            //                FlowHighStatus = "Error";
+            //            }
+            //            else
+            //            {
+            //                FlowHighStatus = "Warning";
+            //            }
+            //            //CMM Flow Low报警灯
+            //            if (ReservoirData.Flow >= _reservoirCMMFlowLowWarning)
+            //            {
+            //                FlowLowStatus = "Normal";
 
-                        }
-                        else if (ReservoirData.Flow < _reservoirCMMFlowLowError)
-                        {
-                            FlowLowStatus = "Error";
-                        }
-                        else
-                        {
-                            FlowLowStatus = "Warning";
-                        }
-                        //High Level报警灯
-                        IsHighLevel = (ReservoirData.WaterLevel > _reservoirHighLevel) ? true : false;
-                        //Low Level报警灯
-                        IsLowLevel = (ReservoirData.WaterLevel < _reservoirLowLevel) ? true : false;
-                        //HighSafety
-                        IsHighSafety = ReservoirData.SafetyHighLevel;
-                        //HedFlow管流
-                        HEDFlowIsOn = (ReservoirData.HedFlow > 0) ? true : false;
-                        //DIReplenFault
-                        IsDiReplenFault = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsDIReplenInFault")
-                        || CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.DIReplenMaxTimeOut");
+            //            }
+            //            else if (ReservoirData.Flow < _reservoirCMMFlowLowError)
+            //            {
+            //                FlowLowStatus = "Error";
+            //            }
+            //            else
+            //            {
+            //                FlowLowStatus = "Warning";
+            //            }
+            //            //High Level报警灯
+            //            IsHighLevel = (ReservoirData.WaterLevel > _reservoirHighLevel) ? true : false;
+            //            //Low Level报警灯
+            //            IsLowLevel = (ReservoirData.WaterLevel < _reservoirLowLevel) ? true : false;
+            //            //HighSafety
+            //            IsHighSafety = ReservoirData.SafetyHighLevel;
+            //            //HedFlow管流
+            //            HEDFlowIsOn = (ReservoirData.HedFlow > 0) ? true : false;
+            //            //DIReplenFault
+            //            IsDiReplenFault = CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.IsDIReplenInFault")
+            //            || CommonFunction.GetValue<bool>(_rtDataValueDic, $"{Module}.DIReplenMaxTimeOut");
 
-                        IsError = State== "Error" ? true : false;
-                    }
+            //            IsError = State== "Error" ? true : false;
+            //        }
                    
-                }
-            }
+            //    }
+            //}
         }
         /// <summary>
         /// 隐藏

+ 14 - 0
PunkHPX8_MainPages/ViewModels/VPWCellViewModel.cs

@@ -0,0 +1,14 @@
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_MainPages.ViewModels
+{
+    public class VPWCellViewModel:BindableBase
+    {
+
+    }
+}

+ 14 - 0
PunkHPX8_MainPages/ViewModels/VPWMainViewModel.cs

@@ -0,0 +1,14 @@
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PunkHPX8_MainPages.ViewModels
+{
+    public class VPWMainViewModel:BindableBase
+    {
+
+    }
+}

+ 193 - 0
PunkHPX8_MainPages/ViewModels/VPWMotionViewModel.cs

@@ -0,0 +1,193 @@
+using MECF.Framework.Common.CommonData.PUF;
+using MECF.Framework.Common.DataCenter;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.Utilities;
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Threading;
+
+namespace PunkHPX8_MainPages.ViewModels
+{
+    public class VPWMotionViewModel : BindableBase
+    {
+        #region 常量
+        private const string MOTION_DATA = "MotionData";
+        private const int ACCEL_FACTOR = 10;
+        #endregion
+
+        #region 内部变量
+
+        #region VPW1Rotation
+        /// <summary>
+        /// VPW1Rotation模块名称
+        /// </summary>
+        private string _vPW1RotationModuleName;
+        /// <summary>
+        /// 数据
+        /// </summary>
+        private CommandMotionData _vPW1RotationMotionData;
+        #endregion
+
+        #region VPW2Rotation
+        /// <summary>
+        /// VPW2Rotation模块名称
+        /// </summary>
+        private string _vPW2RotationModuleName;
+        /// <summary>
+        /// 数据
+        /// </summary>
+        private CommandMotionData _vPW2RotationMotionData;
+        #endregion
+
+
+        /// <summary>
+        /// 增加
+        /// </summary>
+        private double _incrementValue = 0.01;
+        /// <summary>
+        /// 定时器
+        /// </summary>
+        DispatcherTimer _timer;
+        /// <summary>
+        /// RT查询key集合
+        /// </summary>
+        private List<string> _rtDataKeys = new List<string>();
+        /// <summary>
+        /// rt查询key数值字典
+        /// </summary>
+        private Dictionary<string, object> _rtDataValueDic = new Dictionary<string, object>();
+
+        #endregion
+
+        #region 属性
+
+        #region VPW1Rotation
+        /// <summary>
+        /// VPW1Rotation名称
+        /// </summary>
+        public string VPW1RotationModuleName
+        {
+            get { return _vPW1RotationModuleName; }
+            set { SetProperty(ref _vPW1RotationModuleName, value); }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        public CommandMotionData VPW1RotationMotionData
+        {
+            get { return _vPW1RotationMotionData; }
+            set { SetProperty(ref _vPW1RotationMotionData, value); }
+        }
+        #endregion
+
+        #region VPW2Rotation
+        /// <summary>
+        /// VPW2Rotation
+        /// </summary>
+        public string VPW2RotationModuleName
+        {
+            get { return _vPW2RotationModuleName; }
+            set { SetProperty(ref _vPW2RotationModuleName, value); }
+        }
+        /// <summary>
+        /// 
+        /// </summary>
+        public CommandMotionData VPW2RotationMotionData
+        {
+            get { return _vPW2RotationMotionData; }
+            set { SetProperty(ref _vPW2RotationMotionData, value); }
+        }
+        #endregion
+
+
+        /// <summary>
+        /// 步进
+        /// </summary>
+        public double IncrementValue
+        {
+            get { return _incrementValue; }
+            set { SetProperty(ref _incrementValue, value); }
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 加载数据
+        /// </summary>
+        public void LoadData(string systemName)
+        {
+
+            VPW1RotationModuleName = $"{ModuleName.VpwCell1}.Rotation";
+            VPW2RotationModuleName = $"{ModuleName.VpwCell2}.Rotation";
+  
+            _rtDataKeys.Clear();
+
+            _rtDataKeys.Add($"{VPW1RotationModuleName}.IsHomed");
+            _rtDataKeys.Add($"{VPW1RotationModuleName}.IsSwitchOn");
+            _rtDataKeys.Add($"{VPW1RotationModuleName}.{MOTION_DATA}");
+
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.IsHomed");
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.IsSwitchOn");
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.{MOTION_DATA}");
+            
+            if (_timer == null)
+            {
+                _timer = new DispatcherTimer();
+                _timer.Interval = TimeSpan.FromMilliseconds(500);
+                _timer.Tick += Timer_Tick;
+            }
+            _timer.Start();
+        }
+
+        /// <summary>
+        /// 定时器执行
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void Timer_Tick(object sender, EventArgs e)
+        {
+            if (_rtDataKeys.Count != 0)
+            {
+                _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
+                if (_rtDataValueDic != null)
+                {
+
+                    CommandMotionData tmp1 = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{VPW1RotationModuleName}.{MOTION_DATA}");
+                    if (tmp1 != null)
+                    {
+                        tmp1.ActualVelocity = Math.Round(tmp1.ActualVelocity / 6, 2);
+                        tmp1.ProfileVelocity = Math.Round(tmp1.ProfileVelocity / 6, 2);
+                        tmp1.HomingVelocity = Math.Round(tmp1.HomingVelocity / 6, 2);
+                        tmp1.HomingVelocitySlow = Math.Round(tmp1.HomingVelocitySlow / 6, 2);
+                        tmp1.ProfileDecel = tmp1.ProfileDecel * ACCEL_FACTOR;
+                        tmp1.ProfileAccel = tmp1.ProfileAccel * ACCEL_FACTOR;
+                    }
+                    VPW1RotationMotionData = tmp1;
+
+                    CommandMotionData tmp2 = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{VPW2RotationModuleName}.{MOTION_DATA}");
+                    if (tmp2 != null)
+                    {
+                        tmp2.ActualVelocity = Math.Round(tmp1.ActualVelocity / 6, 2);
+                        tmp2.ProfileVelocity = Math.Round(tmp1.ProfileVelocity / 6, 2);
+                        tmp2.HomingVelocity = Math.Round(tmp1.HomingVelocity / 6, 2);
+                        tmp2.HomingVelocitySlow = Math.Round(tmp1.HomingVelocitySlow / 6, 2);
+                        tmp2.ProfileDecel = tmp1.ProfileDecel * ACCEL_FACTOR;
+                        tmp2.ProfileAccel = tmp1.ProfileAccel * ACCEL_FACTOR;
+                    }
+                    VPW2RotationMotionData = tmp2;
+                }
+            }
+        }
+        /// <summary>
+        /// 隐藏
+        /// </summary>
+        public void Hide()
+        {
+            _timer.Stop();
+        }
+    }
+}

+ 208 - 0
PunkHPX8_MainPages/ViewModels/VPWStationSetupViewModel.cs

@@ -0,0 +1,208 @@
+using MECF.Framework.Common.CommonData.PUF;
+using MECF.Framework.Common.DataCenter;
+using MECF.Framework.Common.Equipment;
+using MECF.Framework.Common.Utilities;
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Threading;
+
+namespace PunkHPX8_MainPages.ViewModels
+{
+    public class VPWStationSetupViewModel : BindableBase
+    {
+        #region 常量
+        private const string MOTION_DATA = "MotionData";
+        private const string IS_SWITCH_ON = "IsSwitchOn";
+        private const string CURRENT_STATION = "CurrentStation";
+        #endregion
+
+        #region 内部变量
+
+        #region VPW1Rotation
+        /// <summary>
+        /// VPW1Rotation模块名称
+        /// </summary>
+        private string _vPW1RotationModuleName;
+        /// <summary>
+        /// VPW1Rotation运动数据
+        /// </summary>
+        private CommandMotionData _vPW1RotationMotionData;
+        /// <summary>
+        /// VPW1Rotation当前位置
+        /// </summary>
+        private string _vPW1RotationCurrentStation;
+        #endregion
+
+        #region VPW2Rotation
+        /// <summary>
+        /// VPW2Rotation模块名称
+        /// </summary>
+        private string _vPW2RotationModuleName;
+        /// <summary>
+        /// VPW1Rotation运动数据
+        /// </summary>
+        private CommandMotionData _vPW2RotationMotionData;
+        /// <summary>
+        /// VPW1Rotation当前位置
+        /// </summary>
+        private string _vPW2RotationCurrentStation;
+        #endregion
+
+        #region 系统数据
+        /// <summary>
+        /// 定时器
+        /// </summary>
+        DispatcherTimer _timer;
+        /// <summary>
+        /// 查询后台数据集合
+        /// </summary>
+        private List<string> _rtDataKeys = new List<string>();
+        /// <summary>
+        /// rt查询key数值字典
+        /// </summary>
+        private Dictionary<string, object> _rtDataValueDic = new Dictionary<string, object>();
+
+        #endregion
+
+        #endregion
+
+        #region 属性
+
+
+        #region VPW1Rotation
+        /// <summary>
+        /// VPW1Rotation名称
+        /// </summary>
+        public string VPW1RotationModuleName
+        {
+            get { return _vPW1RotationModuleName; }
+            set { SetProperty(ref _vPW1RotationModuleName, value); }
+        }
+        /// <summary>
+        /// VPW1Rotation运动数据
+        /// </summary>
+        public CommandMotionData VPW1RotationMotionData
+        {
+            get { return _vPW1RotationMotionData; }
+            set { SetProperty(ref _vPW1RotationMotionData, value); }
+        }
+        /// <summary>
+        /// VPW1Rotation当前位置
+        /// </summary>
+        public string VPW1RotationCurrentStation
+        {
+            get { return _vPW1RotationCurrentStation; }
+            set { SetProperty(ref _vPW1RotationCurrentStation, value); }
+        }
+        #endregion
+
+        #region VPW2Rotation
+        /// <summary>
+        /// VPW2Rotation名称
+        /// </summary>
+        public string VPW2RotationModuleName
+        {
+            get { return _vPW2RotationModuleName; }
+            set { SetProperty(ref _vPW2RotationModuleName, value); }
+        }
+        /// <summary>
+        /// VPW2Rotation运动数据
+        /// </summary>
+        public CommandMotionData VPW2RotationMotionData
+        {
+            get { return _vPW2RotationMotionData; }
+            set { SetProperty(ref _vPW2RotationMotionData, value); }
+        }
+        /// <summary>
+        /// VPW1Rotation当前位置
+        /// </summary>
+        public string VPW2RotationCurrentStation
+        {
+            get { return _vPW2RotationCurrentStation; }
+            set { SetProperty(ref _vPW2RotationCurrentStation, value); }
+        }
+        #endregion
+
+        #endregion
+
+        /// <summary>
+        /// 加载数据
+        /// </summary>
+        public void LoadData(string systemName)
+        {
+            VPW1RotationModuleName = $"{ModuleName.VpwCell1}.Rotation";
+            VPW2RotationModuleName = $"{ModuleName.VpwCell2}.Rotation";
+            AddDataKeys();
+            if (_timer == null)
+            {
+                _timer = new DispatcherTimer();
+                _timer.Interval = TimeSpan.FromMilliseconds(200);
+                _timer.Tick += Timer_Tick; ;
+            }
+            _timer.Start();
+
+        }
+        /// <summary>
+        /// 定时器执行
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void Timer_Tick(object sender, EventArgs e)
+        {
+            OnTimer();
+        }
+        /// <summary>
+        /// 隐藏
+        /// </summary>
+        public void Hide()
+        {
+            if (_timer != null)
+            {
+                _timer.Stop();
+            }
+        }
+        /// <summary>
+        /// 初始化查询数据集合
+        /// </summary>
+        private void AddDataKeys()
+        {
+            _rtDataKeys.Clear();
+
+            _rtDataKeys.Add($"{VPW1RotationModuleName}.{MOTION_DATA}");
+            _rtDataKeys.Add($"{VPW1RotationModuleName}.{IS_SWITCH_ON}");
+            _rtDataKeys.Add($"{VPW1RotationModuleName}.{CURRENT_STATION}");
+
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.{MOTION_DATA}");
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.{IS_SWITCH_ON}");
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.{CURRENT_STATION}");
+
+            _rtDataKeys.Add($"{VPW2RotationModuleName}.{CURRENT_STATION}");
+        }
+        /// <summary>
+        /// 定时器
+        /// </summary>
+        /// <returns></returns>
+        private Boolean OnTimer()
+        {
+            if (_rtDataKeys.Count != 0)
+            {
+                _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
+                if (_rtDataValueDic != null)
+                {
+
+                    VPW1RotationMotionData = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{VPW1RotationModuleName}.{MOTION_DATA}");
+                    VPW1RotationCurrentStation = CommonFunction.GetCurrentStationLastContent(CommonFunction.GetValue<string>(_rtDataValueDic, $"{VPW1RotationModuleName}.{CURRENT_STATION}"), VPW1RotationModuleName);
+
+                    VPW2RotationMotionData = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{VPW2RotationModuleName}.{MOTION_DATA}");
+                    VPW2RotationCurrentStation = CommonFunction.GetCurrentStationLastContent(CommonFunction.GetValue<string>(_rtDataValueDic, $"{VPW2RotationModuleName}.{CURRENT_STATION}"), VPW2RotationModuleName); 
+                }
+            }
+            return true;
+        }
+
+    }
+}

+ 15 - 0
PunkHPX8_MainPages/Views/VPWCellView.xaml

@@ -0,0 +1,15 @@
+<UserControl x:Class="PunkHPX8_MainPages.Views.VPWCellView"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:UserControls="clr-namespace:PunkHPX8_Themes.UserControls;assembly=PunkHPX8_Themes" 
+             xmlns:prism="http://prismlibrary.com/"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             xmlns:local="clr-namespace:PunkHPX8_MainPages.Views"
+             mc:Ignorable="d" x:Name="self"
+             d:DesignHeight="850" d:DesignWidth="1800">
+    <Grid>
+            
+    </Grid>
+</UserControl>

+ 28 - 0
PunkHPX8_MainPages/Views/VPWCellView.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PunkHPX8_MainPages.Views
+{
+    /// <summary>
+    /// VPWCellView.xaml 的交互逻辑
+    /// </summary>
+    public partial class VPWCellView : UserControl
+    {
+        public VPWCellView()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 15 - 0
PunkHPX8_MainPages/Views/VPWMainView.xaml

@@ -0,0 +1,15 @@
+<UserControl x:Class="PunkHPX8_MainPages.Views.VPWMainView"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:UserControls="clr-namespace:PunkHPX8_Themes.UserControls;assembly=PunkHPX8_Themes" 
+             xmlns:prism="http://prismlibrary.com/"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             xmlns:local="clr-namespace:PunkHPX8_MainPages.Views"
+             mc:Ignorable="d" x:Name="self"
+             d:DesignHeight="850" d:DesignWidth="1800">
+    <Grid>
+            
+    </Grid>
+</UserControl>

+ 28 - 0
PunkHPX8_MainPages/Views/VPWMainView.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PunkHPX8_MainPages.Views
+{
+    /// <summary>
+    /// VPWMainView.xaml 的交互逻辑
+    /// </summary>
+    public partial class VPWMainView : UserControl
+    {
+        public VPWMainView()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 34 - 0
PunkHPX8_MainPages/Views/VPWMotionView.xaml

@@ -0,0 +1,34 @@
+<UserControl x:Class="PunkHPX8_MainPages.Views.VPWMotionView"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:UserControls="clr-namespace:PunkHPX8_Themes.UserControls;assembly=PunkHPX8_Themes" 
+             xmlns:prism="http://prismlibrary.com/"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             xmlns:local="clr-namespace:PunkHPX8_MainPages.Views"
+             mc:Ignorable="d" x:Name="self"
+             d:DesignHeight="850" d:DesignWidth="1800">
+    <Grid>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition ></ColumnDefinition>
+            <ColumnDefinition Width="450"></ColumnDefinition>
+            <ColumnDefinition Width="450"></ColumnDefinition>
+            <ColumnDefinition Width="450"></ColumnDefinition>
+            <ColumnDefinition Width="450"></ColumnDefinition>
+            <ColumnDefinition ></ColumnDefinition>
+        </Grid.ColumnDefinitions>
+        <UserControls:VPWMotionControl Grid.Column="1" 
+                                ModuleTitle="{Binding VPW1RotationModuleName}" 
+                                ModuleName="{Binding  VPW1RotationModuleName}" 
+                                ModuleUnit="deg" 
+                                MotionData="{Binding VPW1RotationMotionData}" 
+                                IncrementValue="{Binding IncrementValue}"/>
+        <UserControls:VPWMotionControl Grid.Column="2" 
+                                ModuleTitle="{Binding VPW2RotationModuleName}" 
+                                ModuleName="{Binding VPW2RotationModuleName}" 
+                                ModuleUnit="deg" 
+                                MotionData="{Binding VPW2RotationMotionData}" 
+                                IncrementValue="{Binding IncrementValue}"/>
+    </Grid>
+</UserControl>

+ 28 - 0
PunkHPX8_MainPages/Views/VPWMotionView.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PunkHPX8_MainPages.Views
+{
+    /// <summary>
+    /// VPWMotionView.xaml 的交互逻辑
+    /// </summary>
+    public partial class VPWMotionView : UserControl
+    {
+        public VPWMotionView()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 51 - 0
PunkHPX8_MainPages/Views/VPWStationSetupView.xaml

@@ -0,0 +1,51 @@
+<UserControl x:Class="PunkHPX8_MainPages.Views.VPWStationSetupView"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PunkHPX8_MainPages.Views"
+             xmlns:prism="http://prismlibrary.com/"
+             xmlns:UserControls="clr-namespace:PunkHPX8_Themes.UserControls;assembly=PunkHPX8_Themes"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             mc:Ignorable="d" Name="self"
+             d:DesignHeight="600" d:DesignWidth="1500">
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="200"/>
+            <RowDefinition Height="200"/>
+            <RowDefinition Height="200"/>
+            <RowDefinition/>
+        </Grid.RowDefinitions>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="500"></ColumnDefinition>
+            <ColumnDefinition Width="500"></ColumnDefinition>
+            <ColumnDefinition Width="500"></ColumnDefinition>
+            <ColumnDefinition/>
+        </Grid.ColumnDefinitions>
+        <Grid Grid.Row="0" Grid.Column="0">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="380"></ColumnDefinition>
+                <ColumnDefinition/>
+            </Grid.ColumnDefinitions>
+            <UserControls:VPWStationPositionControl HorizontalAlignment="Center" Margin="10,0,0,0" VerticalAlignment="Center" Grid.ColumnSpan="2" Width="430" Height="175"
+                           ModuleTitle="{Binding VPW1RotationModuleName}" 
+                           ModuleName="{Binding VPW1RotationModuleName}" 
+                           CurrentPosition="{Binding VPW1RotationMotionData.MotorPosition}" 
+                           Torque="{Binding VPW1RotationMotionData.Torque}" 
+                           CurrentStation="{Binding VPW1RotationCurrentStation}"/>
+        </Grid>
+        <Grid Grid.Row="0" Grid.Column="2">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="380"></ColumnDefinition>
+                <ColumnDefinition/>
+            </Grid.ColumnDefinitions>
+            <UserControls:VPWStationPositionControl HorizontalAlignment="Center" Margin="10,0,0,0" VerticalAlignment="Center" Grid.ColumnSpan="2" Width="430" Height="175"
+                           ModuleTitle="{Binding VPW2RotationModuleName}" 
+                           ModuleName="{Binding VPW2RotationModuleName}" 
+                           CurrentPosition="{Binding VPW2RotationMotionData.MotorPosition}" 
+                           Torque="{Binding VPW2RotationMotionData.Torque}" 
+                           CurrentStation="{Binding VPW2RotationCurrentStation}"/>
+        </Grid>
+     
+    </Grid>
+</UserControl>

+ 28 - 0
PunkHPX8_MainPages/Views/VPWStationSetupView.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PunkHPX8_MainPages.Views
+{
+    /// <summary>
+    /// VPWSetupView.xaml 的交互逻辑
+    /// </summary>
+    public partial class VPWStationSetupView : UserControl
+    {
+        public VPWStationSetupView()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 28 - 0
PunkHPX8_RT/Config/Devices/AxisProviderCfg.xml

@@ -164,4 +164,32 @@
 	<MotorPositionRate>1</MotorPositionRate>
 	<VelocityRate>64</VelocityRate>
   </Axis>
+  <Axis Name="APW1.Rotation">
+    <Driver>Beckhoff</Driver>
+    <!-- <Driver>Sim</Driver> -->
+    <Units>deg</Units>
+	<!-- 5294 X 4 counts/rev * 1/360 rev/deg = 58.822222 counts/deg -->
+    <ScaleFactor>91</ScaleFactor>
+    <JogLimit>5</JogLimit>
+    <!--Units>rev</Units-->
+	<!-- 5294 X 4 counts/rev = 21176 counts/rev -->
+    <!--ScaleFactor>21176</ScaleFactor-->
+	<MinMoveTime>0.5</MinMoveTime>
+	<MotorPositionRate>1</MotorPositionRate>
+	<VelocityRate>64</VelocityRate>
+  </Axis> 
+  <Axis Name="APW2.Rotation">
+    <Driver>Beckhoff</Driver>
+    <!-- <Driver>Sim</Driver> -->
+    <Units>deg</Units>
+	<!-- 5294 X 4 counts/rev * 1/360 rev/deg = 58.822222 counts/deg -->
+    <ScaleFactor>91</ScaleFactor>
+    <JogLimit>5</JogLimit>
+    <!--Units>rev</Units-->
+	<!-- 5294 X 4 counts/rev = 21176 counts/rev -->
+    <!--ScaleFactor>21176</ScaleFactor-->
+	<MinMoveTime>0.5</MinMoveTime>
+	<MotorPositionRate>1</MotorPositionRate>
+	<VelocityRate>64</VelocityRate>
+  </Axis>
 </Axes>

+ 11 - 4
PunkHPX8_RT/Config/Layout/ToolLayoutConfiguration.xml

@@ -148,7 +148,14 @@
 					<Installed>true</Installed>
 					<CellID>14</CellID>
 					<NominalGantryPositionInMilliMeters>2219</NominalGantryPositionInMilliMeters>
-					<VpwCellID>4</VpwCellID>
+					<VpwCellID>1</VpwCellID>
+					<SubType>Stratus</SubType>
+				</Item>
+				<Item i:type="VpwCell">
+					<Installed>true</Installed>
+					<CellID>15</CellID>
+					<NominalGantryPositionInMilliMeters>2219</NominalGantryPositionInMilliMeters>
+					<VpwCellID>2</VpwCellID>
 					<SubType>Stratus</SubType>
 				</Item>
 			</Cells>
@@ -157,7 +164,7 @@
 		<!-- PREWET -->
 
 		<Item i:type="Prewet">
-			<Installed>true</Installed>
+			<Installed>false</Installed>
 			<CellID>20</CellID>
 			<NominalGantryPositionInMilliMeters>1135</NominalGantryPositionInMilliMeters>
 			<PrewetID>1</PrewetID>
@@ -168,14 +175,14 @@
 		<!-- DRYERs -->
 
 		<Item i:type="Dryer">
-			<Installed>true</Installed>
+			<Installed>false</Installed>
 			<CellID>21</CellID>
 			<NominalGantryPositionInMilliMeters>957</NominalGantryPositionInMilliMeters>
 			<DryerID>1</DryerID>
 			<SubType>HVDHSIndependent</SubType>
 		</Item>
 		<Item i:type="Dryer">
-			<Installed>true</Installed>
+			<Installed>false</Installed>
 			<CellID>22</CellID>
 			<NominalGantryPositionInMilliMeters>873</NominalGantryPositionInMilliMeters>
 			<DryerID>2</DryerID>

+ 5 - 0
PunkHPX8_RT/Devices/VpwCell/VpwCellDevice.cs

@@ -6,6 +6,7 @@ using MECF.Framework.Common.Beckhoff.ModuleIO;
 using MECF.Framework.Common.CommonData.Prewet;
 using MECF.Framework.Common.CommonData.Vpw;
 using MECF.Framework.Common.IOCore;
+using MECF.Framework.Common.Persistent.SRD;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -147,11 +148,13 @@ namespace PunkHPX8_RT.Devices.VpwCell
             OP.Subscribe($"{Module}.DrainValveOff", (cmd, para) => { return DrainValveOff(); });
             OP.Subscribe($"{Module}.VacuumValveOn", (cmd, para) => { return VacuumValveOn(); });
             OP.Subscribe($"{Module}.VacuumValveOff", (cmd, para) => { return VacuumValveOff(); });
+
         }
         #endregion
 
         #region Action
 
+
         #region Flow
         /// <summary>
         /// Flow Drip on
@@ -264,6 +267,8 @@ namespace PunkHPX8_RT.Devices.VpwCell
             return IOModuleManager.Instance.WriteIoValue(ioName, value);
         }
 
+
+
         #endregion
 
         /// <summary>

+ 14 - 0
PunkHPX8_Themes/PunkHPX8_Themes.csproj

@@ -480,6 +480,12 @@
     <Compile Include="UserControls\ProcessSmallFurnace.xaml.cs">
       <DependentUpon>ProcessSmallFurnace.xaml</DependentUpon>
     </Compile>
+    <Compile Include="UserControls\VPWMotionControl.xaml.cs">
+      <DependentUpon>VPWMotionControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="UserControls\VPWStationPositionControl.xaml.cs">
+      <DependentUpon>VPWStationPositionControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="UserControls\WaferCtrl.xaml.cs">
       <DependentUpon>WaferCtrl.xaml</DependentUpon>
     </Compile>
@@ -1019,6 +1025,14 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="UserControls\VPWMotionControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="UserControls\VPWStationPositionControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="UserControls\WaferCtrl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 239 - 0
PunkHPX8_Themes/UserControls/VPWMotionControl.xaml

@@ -0,0 +1,239 @@
+<UserControl x:Class="PunkHPX8_Themes.UserControls.VPWMotionControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PunkHPX8_Themes.UserControls"
+             mc:Ignorable="d" x:Name="self" 
+             xmlns:converters="clr-namespace:PunkHPX8_Themes.Converters"
+             xmlns:Control="clr-namespace:MECF.Framework.UI.Core.Control;assembly=MECF.Framework.UI.Core"
+             d:DesignHeight="850" d:DesignWidth="450">
+    <UserControl.Resources>
+        <converters:BoolToColor x:Key="boolToColor"/>
+        <converters:BoolToRedColor x:Key="boolToRedColor"/>
+    </UserControl.Resources>
+    <Grid>
+        <GroupBox Header="{Binding ModuleTitle, ElementName=self}"  Background="{DynamicResource Table_BD_Title}" BorderBrush="DarkGray">
+            <Grid>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="30"/>
+                    <RowDefinition Height="35"/>
+                    <RowDefinition Height="150"/>
+                    <RowDefinition Height="70"/>
+                    <RowDefinition Height="180"/>
+                    <RowDefinition Height="2"/>
+                    <RowDefinition Height="240"/>
+                    <RowDefinition Height="60"/>
+                    <RowDefinition/>
+                </Grid.RowDefinitions>
+
+                <WrapPanel Grid.Row="0" VerticalAlignment="Center">
+                    <Label Content="Status" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Background="Black" Foreground="Lime" VerticalAlignment="Center" Text="{Binding MotionData.Status, ElementName=self}" 
+                       FontWeight="Bold" FontSize="16"  Width="365"/>
+                </WrapPanel>
+                <Grid Grid.Row="1">
+                    <Button Style="{StaticResource SysBtnStyle}" Width="50" Content="ON" Margin="9,2,359,3" Height="30" Click="SwitchOn_Click"/>
+                    <Ellipse Margin="66,9,336,10"  Width="16" Height="16"  Fill="{Binding MotionData.IsSwitchOn, Converter={StaticResource boolToColor}, ElementName=self}"   Stroke="Silver"/>
+                    <Button Style="{StaticResource SysBtnStyle}" Width="50" Content="OFF" Margin="88,2,280,3" Height="30" Click="SwitchOff_Click"/>
+                    <Button Style="{StaticResource SysBtnStyle}" Width="50" Content="Home" Margin="325,2,43,3" Height="30" Click="Home_Click"/>
+                    <Ellipse Margin="382,9,20,10"  Width="16" Height="16"  Fill="{Binding MotionData.IsHomed, Converter={StaticResource boolToColor}, ElementName=self}"   Stroke="Silver"/>
+                </Grid>
+                <Grid Grid.Row="2">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="220"/>
+                        <ColumnDefinition Width="130"/>
+                        <ColumnDefinition Width="80"/>
+                        <ColumnDefinition Width="*"/>
+                    </Grid.ColumnDefinitions>
+                    <Label Grid.Row="0" Grid.Column="0" Content="Motor Position" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="0" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.MotorPosition, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="0" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self,Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="1" Grid.Column="0" Content="Target Position" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="1" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.TargetPosition, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="1" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self,Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="2" Grid.Column="0" Content="Position Error" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="2" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.PositionError, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="2" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self,Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="3" Grid.Column="0" Content="Torque" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="3" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.ActualTorque, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="3" Grid.Column="2" Margin="2,0,2,0" Text="%" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="4" Grid.Column="0" Content="Velocity" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="4" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding ElementName=self,Path=MotionData.ActualVelocity, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="4" Text="rpm" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                    </TextBlock>
+                </Grid>
+                <Grid Grid.Row="3">
+                    <Button Style="{StaticResource SysBtnStyle}" Width="50" Content="-jog" Margin="104,2,284,38" Height="30" Click="JogDown_Click"/>
+                    <Control:NumbericUpDown HorizontalAlignment="Center" Margin="0,2,0,0" VerticalAlignment="Top"  Width="120" Height="35" MaxValue="100.00" MinValue="-100.00"
+                                    IncrementValue="{Binding ElementName=self,Path=IncrementValue,Mode=TwoWay}" DigitalMaxLength="2" Value="{Binding ElementName=self,Path=JogValue,Mode=TwoWay}"/>
+                    <Button Style="{StaticResource SysBtnStyle}" Width="50" Content="+jog" Margin="285,2,103,38" Height="30" Click="JogUp_Click"/>
+                    <Button Style="{StaticResource SysBtnStyle}" Width="50" Content="Stop" Margin="184,39,204,1" Height="30" Click="JogStop_Click"/>
+                </Grid>
+                <Grid Grid.Row="4">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="180"/>
+                        <ColumnDefinition Width="85"/>
+                        <ColumnDefinition Width="85"/>
+                        <ColumnDefinition Width="80"/>
+                        <ColumnDefinition Width="*"/>
+                    </Grid.ColumnDefinitions>
+                    <Label Grid.Row="0" Grid.Column="0" Content="Speed" FontSize="16" FontWeight="Bold"/>
+                    <Control:NumbericTextBox Grid.Row="0" Grid.Column="1"  Margin="2,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="80" 
+                                     Height="22" Value="{Binding ElementName=self,Path=InputSpeed,StringFormat={}{0:F2},Mode=TwoWay}" TextboxName="ProfileVelocity" 
+                                     KeyOperation="{Binding ElementName=self,Path=KeyDownCommand}"/>
+                    <TextBlock Grid.Column="2" Margin="0,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  
+                       Text="{Binding ElementName=self,Path=MotionData.ProfileVelocity,StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Text="rpm" Grid.Row="0" Grid.Column="3" TextAlignment="Center"  VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+
+                    </TextBlock>
+
+                    <Label Grid.Row="1" Grid.Column="0" Content="Acceleration" FontSize="16" FontWeight="Bold"/>
+                    <Control:NumbericTextBox Grid.Row="1" Grid.Column="1"  Margin="2,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="80" 
+                                     Height="22" Value="{Binding ElementName=self,Path=InputAcceleration,StringFormat={}{0:F2},Mode=TwoWay}" TextboxName="ProfileAccel" 
+                                     KeyOperation="{Binding ElementName=self,Path=KeyDownCommand}"/>
+                    <TextBlock Grid.Row="1" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  
+                       Text="{Binding ElementName=self,Path=MotionData.ProfileAccel, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="1" Grid.Column="3" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                        <TextBlock.Text>
+                            <Binding ElementName="self" Path="ModuleUnit" StringFormat=" {0}/s/s" />
+                        </TextBlock.Text>
+                    </TextBlock>
+
+                    <Label Grid.Row="2" Grid.Column="0" Content="Deceleration" FontSize="16" FontWeight="Bold"/>
+                    <Control:NumbericTextBox Grid.Row="2" Grid.Column="1"  Margin="2,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="80" 
+                  Height="22" Value="{Binding ElementName=self,Path=InputDeceleration,StringFormat={}{0:F2},Mode=TwoWay}" TextboxName="ProfileDecel" 
+                                     KeyOperation="{Binding ElementName=self,Path=KeyDownCommand}"/>
+                    <TextBlock Grid.Row="2" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  
+                    Text="{Binding ElementName=self,Path=MotionData.ProfileDecel, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="2" Grid.Column="3" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                        <TextBlock.Text>
+                            <Binding ElementName="self" Path="ModuleUnit" StringFormat=" {0}/s/s" />
+                        </TextBlock.Text>
+                    </TextBlock>
+
+                    <Label Grid.Row="3" Grid.Column="0" Content="Home Speed Switch" FontSize="16" FontWeight="Bold"/>
+                    <Control:NumbericTextBox Grid.Row="3" Grid.Column="1"  Margin="2,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="80" 
+                                     Height="22" Value="{Binding ElementName=self,Path=InputHomeSpeedSwitch,StringFormat={}{0:F2},Mode=TwoWay}" TextboxName="HomingVelocity" 
+                                     KeyOperation="{Binding ElementName=self,Path=KeyDownCommand}"/>
+                    <TextBlock Grid.Row="3" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center" 
+                       Text="{Binding MotionData.HomingVelocity, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="3" Text="rpm"  Grid.Column="3" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                    </TextBlock>
+
+                    <Label Grid.Row="4" Grid.Column="0" Content="Home Speed Index" FontSize="16" FontWeight="Bold"/>
+                    <Control:NumbericTextBox Grid.Row="4" Grid.Column="1"  Margin="2,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="80" 
+                                     Height="22" Value="{Binding ElementName=self,Path=InputHomeSpeedIndex,StringFormat={}{0:F2},Mode=TwoWay}" TextboxName="HomingVelocitySlow" 
+                                     KeyOperation="{Binding ElementName=self,Path=KeyDownCommand}"/>
+                    <TextBlock Grid.Row="4" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  
+                       Text="{Binding MotionData.HomingVelocitySlow, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="4" Text="rpm"  Grid.Column="3" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                    </TextBlock>
+
+                    <Label Grid.Row="5" Grid.Column="0" Content="Home Accel" FontSize="16" FontWeight="Bold"/>
+                    <Control:NumbericTextBox Grid.Row="5" Grid.Column="1"  Margin="2,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="80"
+                                     Height="22" Value="{Binding ElementName=self,Path=InputHomeAccelDecel,StringFormat={}{0:F2},Mode=TwoWay}" TextboxName="HomingAccel" 
+                                     KeyOperation="{Binding ElementName=self,Path=KeyDownCommand}" />
+                    <TextBlock Grid.Row="5" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  
+                       Text="{Binding MotionData.HomingAccel, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="5" Grid.Column="3" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                        <TextBlock.Text>
+                            <Binding ElementName="self" Path="ModuleUnit" StringFormat=" {0}/s/s" />
+                        </TextBlock.Text>
+                    </TextBlock>
+                </Grid>
+
+                <Grid Grid.Row="6">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                        <RowDefinition Height="30"/>
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="220"/>
+                        <ColumnDefinition Width="130"/>
+                        <ColumnDefinition Width="80"/>
+                        <ColumnDefinition Width="*"/>
+                    </Grid.ColumnDefinitions>
+                    <Label Grid.Row="0" Grid.Column="0" Content="Home Offset" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="0" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.HomeOffset, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="0" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self,Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="1" Grid.Column="0" Content="Position Error Limit" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="1" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.PositionErrorLimit, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="1" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self,Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="2" Grid.Column="0" Content="TargetPosition Error Limit" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="2" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.TargetPositionErrorLimit, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="2" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self,Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="3" Grid.Column="0" Content="Torque Limit" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="3" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding ElementName=self,Path=MotionData.TorqueLimit}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="3" Grid.Column="2" Margin="2,0,2,0" Text="%" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="4" Grid.Column="0" Content="E Stop Deceleration" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="4" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.EStopDeceleration, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="4" Grid.Column="2" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold">
+                        <TextBlock.Text>
+                            <Binding ElementName="self" Path="ModuleUnit" StringFormat=" {0}/s/s" />
+                        </TextBlock.Text>
+                    </TextBlock>
+
+                    <Label Grid.Row="5" Grid.Column="0" Content="E Stop Torque" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="5" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.EStopTorque, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="5" Grid.Column="2" Margin="2,0,2,0" Text="%" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="6" Grid.Column="0" Content="Rev Soft Limit" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="6" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.RevSoftLimit, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="6" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self, Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                    <Label Grid.Row="7" Grid.Column="0" Content="Fwd Soft Limit" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="7" Grid.Column="1" Margin="2,0,2,0" TextAlignment="Center" VerticalAlignment="Center"  Text="{Binding MotionData.FwdSoftLimit, ElementName=self, StringFormat=\{0:F2\}}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Grid.Row="7" Grid.Column="2" Margin="2,0,2,0" Text="{Binding ElementName=self, Path=ModuleUnit}" TextAlignment="Center" VerticalAlignment="Center"  Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                </Grid>
+
+                <Grid Grid.Row="7">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="299*"/>
+                        <ColumnDefinition Width="139*"/>
+                    </Grid.ColumnDefinitions>
+                    <Label  Content="Rev Limit" FontSize="16" FontWeight="Bold" Margin="0,0,181,19" />
+                    <!--<Ellipse Margin="34,24,249,20"  Width="16" Height="16"  Fill="{Binding MotionData.RevLimited, Converter={StaticResource boolToRedColor}, ElementName=self}"   Stroke="Silver"/>-->
+                    <Ellipse Margin="34,24,249,20"  Width="16" Height="16"  Fill="Gray"   Stroke="Silver"/>
+                    <Label  Content="Home Switch" FontSize="16" FontWeight="Bold" Margin="160,0,7,19" />
+                    <!--<Ellipse Margin="194,24,89,20"  Width="16" Height="16"  Fill="{Binding MotionData.HomedSwitched, Converter={StaticResource boolToColor}, ElementName=self}"   Stroke="Silver"/>-->
+                    <Ellipse Margin="194,24,89,20"  Width="16" Height="16"  Fill="Gray"   Stroke="Silver"/>
+                    <Label  Content="Fwd Limit" FontSize="16" FontWeight="Bold" Margin="26,0,15,19" Grid.Column="1" />
+                    <!--<Ellipse Margin="60,24,63,20"  Width="16" Height="16"  Fill="{Binding MotionData.FwdLimited, Converter={StaticResource boolToRedColor}, ElementName=self}"   Stroke="Silver" Grid.Column="1"/>-->
+                    <Ellipse Margin="60,24,63,20"  Width="16" Height="16"  Fill="Gray"   Stroke="Silver" Grid.Column="1"/>
+
+                </Grid>
+            </Grid>
+        </GroupBox>
+
+    </Grid>
+</UserControl>

+ 287 - 0
PunkHPX8_Themes/UserControls/VPWMotionControl.xaml.cs

@@ -0,0 +1,287 @@
+using Aitex.Core.UI.MVVM;
+using Aitex.Core.Utilities;
+using MECF.Framework.Common.CommonData.PUF;
+using MECF.Framework.Common.OperationCenter;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PunkHPX8_Themes.UserControls
+{
+    /// <summary>
+    /// VPWMotionControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class VPWMotionControl : UserControl
+    {
+        #region 属性
+        public static readonly DependencyProperty ModuleNameProperty = DependencyProperty.Register(
+          "ModuleName", typeof(string), typeof(VPWMotionControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// 模块名称
+        /// </summary>
+        public string ModuleName
+        {
+            get
+            {
+                return (string)this.GetValue(ModuleNameProperty);
+            }
+            set
+            {
+                this.SetValue(ModuleNameProperty, value);
+            }
+        }
+        public static readonly DependencyProperty ModuleTitleProperty = DependencyProperty.Register(
+            "ModuleTitle", typeof(string), typeof(VPWMotionControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string ModuleTitle
+        {
+            get
+            {
+                return (string)this.GetValue(ModuleTitleProperty);
+            }
+            set
+            {
+                this.SetValue(ModuleTitleProperty, value);
+            }
+        }
+        public static readonly DependencyProperty ModuleUnitProperty = DependencyProperty.Register(
+           "ModuleUnit", typeof(string), typeof(VPWMotionControl), new FrameworkPropertyMetadata("deg", FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string ModuleUnit
+        {
+            get
+            {
+                return (string)this.GetValue(ModuleUnitProperty);
+            }
+            set
+            {
+                this.SetValue(ModuleUnitProperty, value);
+            }
+        }
+        public static readonly DependencyProperty InputSpeedProperty = DependencyProperty.Register(
+           "InputSpeed", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// InSpeed
+        /// </summary>
+        public double InputSpeed
+        {
+            get
+            {
+                return (double)this.GetValue(InputSpeedProperty);
+            }
+            set
+            {
+                this.SetValue(InputSpeedProperty, value);
+            }
+        }
+        public static readonly DependencyProperty InputAccelerationProperty = DependencyProperty.Register(
+          "InputAcceleration", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// InSpeed
+        /// </summary>
+        public double InputAcceleration
+        {
+            get
+            {
+                return (double)this.GetValue(InputAccelerationProperty);
+            }
+            set
+            {
+                this.SetValue(InputAccelerationProperty, value);
+            }
+        }
+
+        public static readonly DependencyProperty InputDecelerationProperty = DependencyProperty.Register(
+         "InputDeceleration", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// InputDeceleration
+        /// </summary>
+        public double InputDeceleration
+        {
+            get
+            {
+                return (double)this.GetValue(InputDecelerationProperty);
+            }
+            set
+            {
+                this.SetValue(InputDecelerationProperty, value);
+            }
+        }
+        public static readonly DependencyProperty InputHomeSpeedSwitchProperty = DependencyProperty.Register(
+        "InputHomeSpeedSwitch", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// InputHomeSpeedSwitch
+        /// </summary>
+        public double InputHomeSpeedSwitch
+        {
+            get
+            {
+                return (double)this.GetValue(InputHomeSpeedSwitchProperty);
+            }
+            set
+            {
+                this.SetValue(InputHomeSpeedSwitchProperty, value);
+            }
+        }
+
+        public static readonly DependencyProperty InputHomeSpeedIndexProperty = DependencyProperty.Register(
+        "InputHomeSpeedIndex", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// InputHomeSpeedIndex
+        /// </summary>
+        public double InputHomeSpeedIndex
+        {
+            get
+            {
+                return (double)this.GetValue(InputHomeSpeedIndexProperty);
+            }
+            set
+            {
+                this.SetValue(InputHomeSpeedIndexProperty, value);
+            }
+        }
+        public static readonly DependencyProperty JogValueIndexProperty = DependencyProperty.Register(
+        "JogValue", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// JogValue
+        /// </summary>
+        public double JogValue
+        {
+            get
+            {
+                return (double)this.GetValue(JogValueIndexProperty);
+            }
+            set
+            {
+                this.SetValue(JogValueIndexProperty, value);
+            }
+        }
+        public static readonly DependencyProperty InputHomeAccelDecelProperty = DependencyProperty.Register(
+        "InputHomeAccelDecel", typeof(double), typeof(VPWMotionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// InputHomeAccelDecel
+        /// </summary>
+        public double InputHomeAccelDecel
+        {
+            get
+            {
+                return (double)this.GetValue(InputHomeAccelDecelProperty);
+            }
+            set
+            {
+                this.SetValue(InputHomeAccelDecelProperty, value);
+            }
+        }
+        public static readonly DependencyProperty MotionDataProperty = DependencyProperty.Register(
+          "MotionData", typeof(CommandMotionData), typeof(VPWMotionControl), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnItemsSourceChanged)));
+        /// <summary>
+        /// MotionData
+        /// </summary>
+        public CommandMotionData MotionData
+        {
+            get
+            {
+                return (CommandMotionData)this.GetValue(MotionDataProperty);
+            }
+            set
+            {
+                this.SetValue(MotionDataProperty, value);
+            }
+        }
+        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (e.NewValue != null)
+            {
+                CommandMotionData data = (CommandMotionData)e.NewValue;
+                d.SetValue(InputSpeedProperty, data.FileProfileVelocity);
+                d.SetValue(InputAccelerationProperty, data.FileAcceleration);
+                d.SetValue(InputDecelerationProperty, data.FileDeceleration);
+                d.SetValue(InputHomeSpeedSwitchProperty, data.FileHomingVelocity);
+                d.SetValue(InputHomeSpeedIndexProperty, data.FileHomingVelocitySlow);
+                d.SetValue(InputHomeAccelDecelProperty, data.FileHomingAccel);
+            }
+        }
+        public static readonly DependencyProperty IncrementValueProperty = DependencyProperty.Register("IncrementValue", typeof(double), typeof(VPWMotionControl));
+        /// <summary>
+        /// 当前位置
+        /// </summary>
+        public double IncrementValue
+        {
+            get
+            {
+                return (double)this.GetValue(IncrementValueProperty);
+            }
+            set
+            {
+                this.SetValue(IncrementValueProperty, Math.Round(value, 2));
+            }
+        }
+
+        [IgnorePropertyChange]
+        public ICommand KeyDownCommand
+        {
+            get;
+            private set;
+        }
+        #endregion
+        public VPWMotionControl()
+        {
+            KeyDownCommand = new DelegateCommand<object[]>(KeyDownAction);
+            InitializeComponent();
+        }
+
+        private void KeyDownAction(object[] param)
+        {
+            if (param.Length >= 2)
+            {
+                if (double.TryParse(param[1].ToString(), out double paramValue))
+                {
+                    InvokeClient.Instance.Service.DoOperation($"{ModuleName}.KeyDown", param[0].ToString(), paramValue);
+                }
+            }
+        }
+
+        private void JogDown_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.JogDown", "TargetPosition", JogValue, MotionData.MotorPosition);
+        }
+        private void JogUp_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.JogUp", "TargetPosition", JogValue, MotionData.MotorPosition);
+        }
+        private void JogStop_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.Stop");
+        }
+
+        private void SwitchOn_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.SwitchOn");
+        }
+
+        private void SwitchOff_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.SwitchOff");
+        }
+
+        private void Home_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.Home");
+        }
+    }
+}

+ 72 - 0
PunkHPX8_Themes/UserControls/VPWStationPositionControl.xaml

@@ -0,0 +1,72 @@
+<UserControl x:Class="PunkHPX8_Themes.UserControls.VPWStationPositionControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="PunkHPX8_Themes.UserControls"
+             xmlns:converters="clr-namespace:PunkHPX8_Themes.Converters"
+             xmlns:customControls="clr-namespace:PunkHPX8_Themes.CustomControls"
+             xmlns:Control="clr-namespace:MECF.Framework.UI.Core.Control;assembly=MECF.Framework.UI.Core" 
+             mc:Ignorable="d" x:Name="self"
+             d:DesignHeight="160" d:DesignWidth="400" Loaded="Self_Loaded">
+    <UserControl.Resources>
+        <converters:BoolToColor x:Key="boolToColor"/>
+    </UserControl.Resources>
+    <Grid>
+        <GroupBox Header="{Binding ModuleTitle, ElementName=self}"  Background="{DynamicResource Table_BD_Title}" BorderBrush="DarkGray">
+            <Grid>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="30"/>
+                    <RowDefinition Height="30"/>
+                    <RowDefinition Height="30"/>
+                    <RowDefinition Height="30"/>
+                    <RowDefinition Height="30"/>
+                    <RowDefinition/>
+                </Grid.RowDefinitions>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="130"/>
+                    <ColumnDefinition Width="135"/>
+                    <ColumnDefinition Width="120"/>
+                </Grid.ColumnDefinitions>
+                <ComboBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="7,2" ItemsSource="{Binding ElementName=self,Path=ModuleItemSource}" SelectedItem="{Binding ElementName=self,Path=ModuleSelectedItem,Mode=TwoWay}"/>
+                <WrapPanel Grid.Row="0" Grid.Column="2" >
+                    <Label Height="40" FontSize="14" Content="At Station" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+                    <Ellipse Margin="5,0"  Width="16" Height="16"  Fill="{Binding IsAtStation, Converter={StaticResource boolToColor}, ElementName=self}"   Stroke="Silver"/>
+                </WrapPanel>
+
+                <Label Grid.Row="1" Grid.Column="0" Content="Saved Position" VerticalAlignment="Center" Margin="2" FontSize="14" FontWeight="Bold"/>
+                <WrapPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="0,0,5,0">
+                    <TextBlock Width="80" Text="{Binding SavedPosition, ElementName=self, StringFormat=\{0:F2\},Mode=TwoWay}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Margin="2,0" Width="45" Text="deg" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                </WrapPanel>
+                <Button Style="{StaticResource SysBtnStyle}"  Content="Goto Saved Pos" Grid.Column="2" Grid.Row="1" Height="25" FontSize="13" Click="SavedPos_Click" Margin="0,2,0,3"/>
+
+                <Label Grid.Row="2" Grid.Column="0" Content="Current Position" VerticalAlignment="Center" Margin="2" FontSize="14" FontWeight="Bold"/>
+                <WrapPanel Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="0,0,5,0">
+                    <TextBlock Width="80" Text="{Binding CurrentPosition, ElementName=self, StringFormat=\{0:F2\},Mode=TwoWay}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Margin="2,0" Width="45" Text="deg" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                </WrapPanel>
+
+                <Button Style="{StaticResource SysBtnStyle}"  Content="Save Motor Pos" Grid.Column="2" Grid.Row="2" Height="25" FontSize="13" Click="MotorPos_Click" Margin="0,3,0,2"/>
+                <customControls:PathButton Grid.Row="3" Grid.Column="0" PathData="{StaticResource Ico_LeftDbArrow}"  DefaultFillBrush="White"  Click="LeftCommand_Click"  Width="40" Height="25" Margin="80,2,10,2" />
+                <WrapPanel Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="0,0,5,0">
+                    <Control:NumbericUpDown Height="30" Width="80" Value="{Binding ElementName=self,Path=DegValue,Mode=TwoWay}" IncrementValue="{Binding ElementName=self,Path=IncrementValue}"/>
+                    <TextBlock Margin="2,0" Width="45" Height="22" Text="deg" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+
+                </WrapPanel>
+                <customControls:PathButton Grid.Row="3" Grid.Column="2" PathData="{StaticResource Ico_RightDbArrow}"  DefaultFillBrush="White"   Click="RightCommand_Click"  Width="40" Height="25" Margin="0,2,80,2" />
+                <Label Grid.Row="4" Grid.Column="0" Content="Torque" VerticalAlignment="Center" Margin="2" FontSize="14" FontWeight="Bold"/>
+                <WrapPanel Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Margin="0,0,5,0">
+                    <TextBlock Width="80" Text="{Binding Torque, ElementName=self, StringFormat=\{0:F2\},Mode=TwoWay}" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                    <TextBlock Margin="2,0" Width="45" Text="%" Background="Black" Foreground="Lime" FontSize="16" FontWeight="Bold"/>
+                </WrapPanel>
+
+                <WrapPanel Grid.Row="4" Grid.Column="2">
+                    <Label Height="30" Content="Station" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center"/>
+                    <Label Height="30" Content="{Binding ElementName=self,Path=CurrentStation}" Foreground="DarkBlue" FontWeight="Bold" VerticalContentAlignment="Center" HorizontalContentAlignment="Left" 
+        VerticalAlignment="Center" HorizontalAlignment="Center" Width="68"/>
+                </WrapPanel>
+            </Grid>
+        </GroupBox>
+    </Grid>
+</UserControl>

+ 425 - 0
PunkHPX8_Themes/UserControls/VPWStationPositionControl.xaml.cs

@@ -0,0 +1,425 @@
+using MECF.Framework.Common.Beckhoff.AxisProvider;
+using MECF.Framework.Common.Beckhoff.Station;
+using MECF.Framework.Common.DataCenter;
+using MECF.Framework.Common.OperationCenter;
+using MECF.Framework.Common.Utilities;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace PunkHPX8_Themes.UserControls
+{
+    /// <summary>
+    /// VPWStationPositionControl.xaml 的交互逻辑
+    /// </summary>
+    public partial class VPWStationPositionControl : UserControl
+    {
+        #region 内部变量
+        /// <summary>
+        /// 步进
+        /// </summary>
+        private double _incrementValue;
+        /// <summary>
+        /// 查询后台数据集合
+        /// </summary>
+        private List<string> _rtDataKeys = new List<string>();
+        /// <summary>
+        /// 查询后台的数据
+        /// </summary>
+        private Dictionary<string, object> _rtDataValues;
+        /// <summary>
+        /// axis
+        /// </summary>
+        BeckhoffStationAxis _axis;
+        /// <summary>
+        /// Stations
+        /// </summary>
+        private List<string> _moduleStations;
+        /// <summary>
+        /// 选择项
+        /// </summary>
+        private string _moduleSelectedItem;
+        /// <summary>
+        /// 已经保存的位置
+        /// </summary>
+        private double _savePosition;
+        /// <summary>
+        /// scaleFactor
+        /// </summary>
+        private double _scaleFactor;
+        #endregion
+
+        #region 属性
+        public static readonly DependencyProperty ModuleNameProperty = DependencyProperty.Register(
+           "ModuleName", typeof(string), typeof(VPWStationPositionControl),
+           new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// 模块名称
+        /// </summary>
+        public string ModuleName
+        {
+            get
+            {
+                return (string)this.GetValue(ModuleNameProperty);
+            }
+            set
+            {
+                this.SetValue(ModuleNameProperty, value);
+            }
+        }
+
+        public List<string> ModuleItemSource
+        {
+            get { return _moduleStations; }
+            set
+            {
+                _moduleStations = value;
+                InvokePropertyChanged(nameof(ModuleItemSource));
+            }
+
+        }
+        public static readonly DependencyProperty IsAtStationProperty = DependencyProperty.Register(
+          "IsAtStation", typeof(bool), typeof(VPWStationPositionControl));
+
+        public bool IsAtStation
+        {
+            get
+            {
+                return (bool)this.GetValue(IsAtStationProperty);
+            }
+            set
+            {
+                SetValue(IsAtStationProperty, value);
+                InvokePropertyChanged(nameof(IsAtStation));
+            }
+        }
+
+        /// <summary>
+        /// 选项索引
+        /// </summary>
+        public string ModuleSelectedItem
+        {
+            get
+            {
+                return _moduleSelectedItem;
+            }
+            set
+            {
+                SavedPosition = GetStationPosition(_axis, value);
+                _moduleSelectedItem = value;
+                InvokePropertyChanged(nameof(ModuleSelectedItem));
+            }
+        }
+        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
+           "OperationCommand", typeof(ICommand), typeof(VPWStationPositionControl),
+           new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
+        public ICommand OperationCommand
+        {
+            get
+            {
+                return (ICommand)this.GetValue(CommandProperty);
+            }
+            set
+            {
+                this.SetValue(CommandProperty, value);
+            }
+        }
+        public static readonly DependencyProperty ModuleTitleProperty = DependencyProperty.Register(
+            "ModuleTitle", typeof(string), typeof(VPWStationPositionControl),
+            new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string ModuleTitle
+        {
+            get
+            {
+                return (string)this.GetValue(ModuleTitleProperty);
+            }
+            set
+            {
+                this.SetValue(ModuleTitleProperty, value);
+            }
+        }
+        public static readonly DependencyProperty SavedPositionProperty = DependencyProperty.Register(
+           "SavedPosition", typeof(double), typeof(VPWStationPositionControl), new FrameworkPropertyMetadata(0.00, new PropertyChangedCallback(OnCurrentPositionChanged)));
+        /// <summary>
+        /// 保存位置
+        /// </summary>
+        public double SavedPosition
+        {
+            get
+            {
+                return _savePosition;
+            }
+            set
+            {
+                _savePosition = value;
+                SetValue(SavedPositionProperty, value);
+                IsAtStation = JudgeAtStation(value, CurrentPosition, ToleranceDefault);
+                InvokePropertyChanged(nameof(SavedPosition));
+            }
+        }
+
+        public static readonly DependencyProperty ToleranceDefaultProperty = DependencyProperty.Register(
+           "ToleranceDefault", typeof(double), typeof(VPWStationPositionControl), new FrameworkPropertyMetadata(0.00, new PropertyChangedCallback(OnCurrentPositionChanged)));
+        /// <summary>
+        /// 保存位置
+        /// </summary>
+        public double ToleranceDefault
+        {
+            get
+            {
+                if (_axis != null)
+                {
+                    return _axis.ToleranceDefault;
+                }
+                else
+                {
+                    return 0;
+                }
+            }
+            set
+            {
+                SetValue(ToleranceDefaultProperty, _axis != null ? _axis.ToleranceDefault : 0);
+            }
+        }
+        public static readonly DependencyProperty CurrentPositionProperty = DependencyProperty.Register(
+           "CurrentPosition", typeof(double), typeof(VPWStationPositionControl), new FrameworkPropertyMetadata(0.00, new PropertyChangedCallback(OnCurrentPositionChanged)));
+        /// <summary>
+        /// 当前位置
+        /// </summary>
+        public double CurrentPosition
+        {
+            get
+            {
+                return (double)this.GetValue(CurrentPositionProperty);
+            }
+            set
+            {
+                SetValue(CurrentPositionProperty, value);
+            }
+        }
+        private static void OnCurrentPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (e.NewValue != null)
+            {
+                double tmpSavedPosition = (double)d.GetValue(SavedPositionProperty);
+                double toleranceDefault = (double)d.GetValue(ToleranceDefaultProperty);
+                bool result = JudgeAtStation(tmpSavedPosition, (double)e.NewValue, toleranceDefault);
+                d.SetValue(IsAtStationProperty, result);
+            }
+        }
+
+        public static readonly DependencyProperty DegValueProperty = DependencyProperty.Register(
+         "DegValue", typeof(double), typeof(VPWStationPositionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+        /// <summary>
+        /// jog value
+        /// </summary>
+        public double DegValue
+        {
+            get
+            {
+                return (double)this.GetValue(DegValueProperty);
+            }
+            set
+            {
+                this.SetValue(DegValueProperty, value);
+            }
+        }
+        public static readonly DependencyProperty TorqueProperty = DependencyProperty.Register(
+       "Torque", typeof(double), typeof(VPWStationPositionControl), new FrameworkPropertyMetadata(0.00, FrameworkPropertyMetadataOptions.AffectsRender));
+
+        /// <summary>
+        /// Torque
+        /// </summary>
+        public double Torque
+        {
+            get
+            {
+                return (double)this.GetValue(TorqueProperty);
+            }
+            set
+            {
+                this.SetValue(TorqueProperty, value);
+            }
+        }
+        public static readonly DependencyProperty CurrentStationProperty = DependencyProperty.Register("CurrentStation", typeof(string), typeof(VPWStationPositionControl));
+        /// <summary>
+        /// 当前位置
+        /// </summary>
+        public string CurrentStation
+        {
+            get
+            {
+                return (string)this.GetValue(CurrentStationProperty);
+            }
+            set
+            {
+                this.SetValue(CurrentStationProperty, value);
+            }
+        }
+        /// <summary>
+        /// 当前位置
+        /// </summary>
+        public double IncrementValue
+        {
+            get { return _incrementValue; }
+            set
+            {
+                _incrementValue = value;
+                InvokePropertyChanged(nameof(IncrementValue));
+            }
+        }
+        public event PropertyChangedEventHandler PropertyChanged;
+        #endregion
+        public VPWStationPositionControl()
+        {
+            InitializeComponent();
+        }
+
+        private void SavedPos_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.GotoSavedPosition", "TargetPosition", ModuleSelectedItem);
+        }
+
+        private void MotorPos_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.Save", $"{ModuleSelectedItem}", Math.Round(CurrentPosition, 2));
+            SavedPosition = CurrentPosition;
+            foreach (Station item in _axis.Stations)
+            {
+                if (item.Name == ModuleSelectedItem)
+                {
+                    item.Position = CurrentPosition.ToString();
+                    break;
+                }
+            }
+        }
+
+        private void LeftCommand_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.JogDown", "TargetPosition", DegValue, CurrentPosition);
+        }
+
+        private void RightCommand_Click(object sender, RoutedEventArgs e)
+        {
+            InvokeClient.Instance.Service.DoOperation($"{ModuleName}.JogUp", "TargetPosition", DegValue, CurrentPosition);
+        }
+        /// <summary>
+        /// 加载
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void Self_Loaded(object sender, RoutedEventArgs e)
+        {
+            if (!string.IsNullOrEmpty(ModuleName))
+            {
+                _rtDataKeys.Clear();
+                IncrementValue = (double)QueryDataClient.Instance.Service.GetConfig("System.Increment");
+                _rtDataKeys.Add($"Station.{ModuleName}");
+                _rtDataKeys.Add($"{ModuleName}.AxisProvider");
+                _rtDataValues = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
+                _axis = CommonFunction.GetValue<BeckhoffStationAxis>(_rtDataValues, $"Station.{ModuleName}");
+                BeckhoffProviderAxis beckhoffProviderAxis = CommonFunction.GetValue<BeckhoffProviderAxis>(_rtDataValues, $"{ModuleName}.AxisProvider");
+                if (_axis != null)
+                {
+                    ToleranceDefault = _axis.ToleranceDefault;
+                    ModuleItemSource = GetStationList(_axis);
+                    if (ModuleItemSource != null && ModuleItemSource.Count != 0)
+                    {
+                        ModuleSelectedItem = ModuleItemSource[0];
+                    }
+                }
+
+                if (beckhoffProviderAxis != null)
+                {
+                    _scaleFactor = beckhoffProviderAxis.ScaleFactor;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 获取工位集合
+        /// </summary>
+        /// <param name="stationAxis"></param>
+        /// <returns></returns>
+        private List<string> GetStationList(BeckhoffStationAxis stationAxis)
+        {
+            List<string> lst = new List<string>();
+            if (stationAxis == null)
+            {
+                return lst;
+            }
+            foreach (var item in stationAxis.Stations)
+            {
+                lst.Add(item.Name);
+            }
+            return lst;
+        }
+        /// <summary>
+        /// 获取工位位置
+        /// </summary>
+        /// <param name="stationAxis"></param>
+        /// <param name="station"></param>
+        /// <returns></returns>
+        private double GetStationPosition(BeckhoffStationAxis stationAxis, string station)
+        {
+            if (stationAxis == null)
+            {
+                return 0;
+            }
+            foreach (var item in stationAxis.Stations)
+            {
+                if (item.Name == station)
+                {
+                    double.TryParse(item.Position, out var position);
+                    return position;
+                }
+            }
+            return 0;
+        }
+        /// <summary>
+        /// 转换数值
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        private int ConvertValue(double value)
+        {
+            if (_scaleFactor != 0)
+            {
+                return (int)Math.Round(value * _scaleFactor, 0);
+            }
+            else
+            {
+                return (int)Math.Round(value, 0);
+            }
+        }
+        private void InvokePropertyChanged(string propertyName)
+        {
+            if (PropertyChanged != null)
+            {
+                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+            }
+        }
+        /// <summary>
+        /// 判定AtStation
+        /// </summary>
+        private static bool JudgeAtStation(double saved, double current, double tolerance)
+        {
+            return Math.Abs(saved - current) <= tolerance;
+        }
+    }
+}

+ 45 - 42
PunkHPX8_UI/Config/UIMenu.json

@@ -303,74 +303,85 @@
 				]
 			},
 			{
-				"Id": "Modules",
-				"Name": "Modules",
+				"Id": "VPW",
+				"Name": "VPW",
 				"IsShow": "true",
 				"MenuItem": [
 					{
-						"Id": "Dryer2",
-						"ModuleName": "Dryer2",
-						"Name": "Dryer2",
+						"Id": "VPWMain",
+						"ModuleName": "VPWMain",
+						"Name": "VPWMain",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "DryerHomePageView"
+						"View": "VPWMainView"
 					},
 					{
-						"Id": "Dryer1",
-						"ModuleName": "Dryer1",
-						"Name": "Dryer1",
+						"Id": "VPW1",
+						"ModuleName": "VPW1",
+						"Name": "VPW1",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "DryerHomePageView"
+						"View": "VPWCellView"
 					},
 					{
-						"Id": "Prewet1",
-						"ModuleName": "Prewet1",
-						"Name": "Prewet1",
+						"Id": "VPW2",
+						"ModuleName": "VPW2",
+						"Name": "VPW2",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "PrewetHomePageView"
+						"View": "VPWCellView"
 					},
 					{
-						"Id": "Metal4",
-						"ModuleName": "Metal4",
-						"Name": "Metal4",
+						"Id": "VPWStationSetup",
+						"ModuleName": "VPWStationSetup",
+						"Name": "VPWSetup",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "MetalSHHomePageView"
+						"View": "VPWStationSetupView"
 					},
 					{
-						"Id": "Rinse4",
-						"ModuleName": "Rinse4",
-						"Name": "Rinse4",
+						"Id": "VPWMotion",
+						"ModuleName": "VPWMotion",
+						"Name": "VPWMotion",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "RinseHomePageView"
-					},
+						"View": "VPWMotionView"
+					}
+
+				]
+			},
+			{
+				"Id": "Modules",
+				"Name": "Modules",
+				"IsShow": "true",
+				"MenuItem": [
 					{
-						"Id": "Metal3",
-						"ModuleName": "Metal3",
-						"Name": "Metal3",
+						"Id": "Prewet1",
+						"ModuleName": "Prewet1",
+						"Name": "Prewet1",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "MetalSHHomePageView"
+						"View": "PrewetHomePageView"
 					},
+					
 					{
-						"Id": "Rinse3",
-						"ModuleName": "Rinse3",
-						"Name": "Rinse3",
+						"Id": "Rinse4",
+						"ModuleName": "Rinse4",
+						"Name": "Rinse4",
 						"IsInit": "true",
 						"IsShow": "true",
 						"View": "RinseHomePageView"
 					},
+					
 					{
-						"Id": "Metal2",
-						"ModuleName": "Metal2",
-						"Name": "Metal2",
+						"Id": "Rinse3",
+						"ModuleName": "Rinse3",
+						"Name": "Rinse3",
 						"IsInit": "true",
 						"IsShow": "true",
-						"View": "MetalSHHomePageView"
+						"View": "RinseHomePageView"
 					},
+					
 					{
 						"Id": "Rinse2",
 						"ModuleName": "Rinse2",
@@ -380,14 +391,6 @@
 						"View": "RinseHomePageView"
 					},
 					{
-						"Id": "Metal1",
-						"ModuleName": "Metal1",
-						"Name": "Metal1",
-						"IsInit": "true",
-						"IsShow": "true",
-						"View": "MetalSHHomePageView"
-					},
-					{
 						"Id": "Rinse1",
 						"ModuleName": "Rinse1",
 						"Name": "Rinse1",

+ 112 - 18
PunkHPX8_UI/Config/UIMenu_permission.json

@@ -192,6 +192,34 @@
 						]
 					},
 					{
+						"MenuName": "VPW",
+						"Menus": [
+							{
+								"MenuName": "VPWMain",
+								"Permission": 2
+							},
+							{
+								"MenuName": "VPW1",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPW2",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPWSetup",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPWMotion",
+								"Permission": 2
+							}
+						]
+					},
+					{
 						"MenuName": "Modules",
 						"Menus": [
 							{
@@ -535,6 +563,36 @@
 						]
 					},
 					{
+						"MenuName": "VPW",
+						"Menus": [
+			
+							{
+								"MenuName": "VPWMain",
+								"Permission": 2
+							},
+							{
+								"MenuName": "VPW1",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPW2",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPWSetup",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPWMotion",
+								"Permission": 2
+							}
+
+						]
+					},
+					{
 						"MenuName": "Modules",
 						"Menus": [
 							{
@@ -877,46 +935,52 @@
 						]
 					},
 					{
-						"MenuName": "Modules",
+						"MenuName": "VPW",
 						"Menus": [
+	
 							{
-								"MenuName": "Dryer2",
+								"MenuName": "VPWMain",
 								"Permission": 2
 							},
 							{
-								"MenuName": "Dryer1",
-								"Permission": 2
-							},
-							{
-								"MenuName": "Prewet1",
+								"MenuName": "VPW1",
 								"Permission": 2
-							},
+							}
+							,
 							{
-								"MenuName": "Rinse4",
+								"MenuName": "VPW2",
 								"Permission": 2
-							},
+							}
+							,
 							{
-								"MenuName": "Rinse3",
+								"MenuName": "VPWSetup",
 								"Permission": 2
-							},
+							}
+							,
 							{
-								"MenuName": "Metal4",
+								"MenuName": "VPWMotion",
 								"Permission": 2
-							},
+							}
+
+						]
+					},
+					{
+						"MenuName": "Modules",
+						"Menus": [
 							{
-								"MenuName": "Rinse2",
+								"MenuName": "Prewet1",
 								"Permission": 2
 							},
 							{
-								"MenuName": "Metal3",
+								"MenuName": "Rinse4",
 								"Permission": 2
 							},
 							{
-								"MenuName": "Metal2",
+								"MenuName": "Rinse3",
 								"Permission": 2
 							},
 							{
-								"MenuName": "Metal1",
+								"MenuName": "Rinse2",
 								"Permission": 2
 							},
 							{
@@ -1236,6 +1300,36 @@
 						]
 					},
 					{
+						"MenuName": "VPW",
+						"Menus": [
+
+							{
+								"MenuName": "VPWMain",
+								"Permission": 2
+							},
+							{
+								"MenuName": "VPW1",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPW2",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPWSetup",
+								"Permission": 2
+							}
+							,
+							{
+								"MenuName": "VPWMotion",
+								"Permission": 2
+							}
+
+						]
+					},
+					{
 						"MenuName": "Modules",
 						"Menus": [
 							{