diff --git a/Rs.SkyLine/Commom/GlobalVar.cs b/Rs.SkyLine/Commom/GlobalVar.cs index 1d4389a..321fc77 100644 --- a/Rs.SkyLine/Commom/GlobalVar.cs +++ b/Rs.SkyLine/Commom/GlobalVar.cs @@ -388,8 +388,36 @@ namespace Rs.Framework return SysConfigParam.GetValue(nameof(PressLowSpeedOffset)); } } + /// + /// 虚拟轴运动 + /// + public static bool VirtualAxis + { + get + { + return SysConfigParam.GetValue(nameof(VirtualAxis)); + } + } + /// + /// 虚拟轴运动时间 + /// + public static int VirtualAxisMoveTime + { + get + { + return SysConfigParam.GetValue(nameof(VirtualAxisMoveTime)); + } + } - public static bool VirtualAxis = true; - public static int VirtualAxisMoveTime = 500; + /// + /// 排料顺序是否是从左到右 + /// + public static bool OrderByLeftToRight + { + get + { + return SysConfigParam.GetValue(nameof(OrderByLeftToRight)); + } + } } } diff --git a/Rs.SkyLine/Commom/Ops.cs b/Rs.SkyLine/Commom/Ops.cs index d0eb184..4ab00fc 100644 --- a/Rs.SkyLine/Commom/Ops.cs +++ b/Rs.SkyLine/Commom/Ops.cs @@ -124,11 +124,10 @@ namespace Rs.MotionPlat.Commom } NozzleManager.Init(); TrayPointManager.LoadPoint(); - TestCenter.Instance.Init(); TurnoverSlotOffset.Init(); MonitorSystemButton.Instance.Start(); TakeTrayFlow.Instance.Start(); - + TestCenter.Instance.Init(); //StockManager.Instance.ChangeStatus(EStockType.Empty1, AutoDischarge.V3.Flow.ETrayStatus.Loaded); //StockManager.Instance.ChangeStatus(EStockType.Input, AutoDischarge.V3.Flow.ETrayStatus.Loaded); diff --git a/Rs.SkyLine/Flow/HomeFlow.cs b/Rs.SkyLine/Flow/HomeFlow.cs index ebf1664..ac49eda 100644 --- a/Rs.SkyLine/Flow/HomeFlow.cs +++ b/Rs.SkyLine/Flow/HomeFlow.cs @@ -205,7 +205,7 @@ namespace Rs.MotionPlat.Flow case 7: if (Ops.IsStop("LoadX", "LoadY", "NozzleR1", "NozzleR2", "NozzleR3", "NozzleR4", "NozzleR5", "NozzleR6", "NozzleR7", "NozzleR8", "NozzleR9")) { - MachineManage.Instance.RunStatus = Commom.ERunStatus.Stopped; + MachineManage.Instance.SetCenterMachineStatus(ERunStatus.Stopped); MessageQueue.Instance.Insert("Device home ok"); MachineManage.Instance.MachineStatus = EMachineStatus.Homed; m_bHomed = true; diff --git a/Rs.SkyLine/Flow/MachineManage.cs b/Rs.SkyLine/Flow/MachineManage.cs index fe6d094..cf67f39 100644 --- a/Rs.SkyLine/Flow/MachineManage.cs +++ b/Rs.SkyLine/Flow/MachineManage.cs @@ -69,12 +69,12 @@ namespace Rs.MotionPlat.Flow /// /// 上下料状态(Waiting,Busying,Unloading,Error,Interrupt,) /// - public ERunState RunState { get; set; } = ERunState.Interrupt; + private ERunState RunState { get; set; } = ERunState.Interrupt; /// /// 设备运行状态(Started,Stopped,InAlarm,EMGStop) /// - public ERunStatus RunStatus { get; set; } = ERunStatus.Stopped; + private ERunStatus RunStatus { get; set; } = ERunStatus.Stopped; /// /// 运行模式(Manual,Automatic) @@ -102,6 +102,15 @@ namespace Rs.MotionPlat.Flow RunStatus= status; } + /// + /// 获取中控运行状态 + /// + /// + public ERunStatus GetCenterRunStatus() + { + return RunStatus; + } + /// /// 设置本地运行状态 /// @@ -119,5 +128,14 @@ namespace Rs.MotionPlat.Flow { RunState= status; } + + /// + /// 获取上下料的状态 + /// + /// + public ERunState GetLoadUnloadStatus() + { + return RunState; + } } } diff --git a/Rs.SkyLine/Flow/RearrangeFlow.cs b/Rs.SkyLine/Flow/RearrangeFlow.cs new file mode 100644 index 0000000..1a11721 --- /dev/null +++ b/Rs.SkyLine/Flow/RearrangeFlow.cs @@ -0,0 +1,585 @@ +using Rs.Camera; +using Rs.Controls; +using Rs.Framework; +using Rs.Motion; +using Rs.MotionPlat.Commom; +using Rs.MotionPlat.MsgBox; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Rs.MotionPlat.Flow +{ + enum ERearrangeFlowStep + { + 等待任务, + 到取料位上方, + 等待到取料位上方, + 到取料位下方, + 等待到取料位下方, + 开真空, + 取料真空检测, + 取料完成抬起, + 等待取料完成抬起, + 到放料位上方, + 等待到放料位上方, + 到放料位下方, + 等待到放料位下方, + 到放料破真空位, + 等待到放料破真空位, + 放料完成抬起, + 等待放料完成抬起, + 放料真空检测, + 放料任务完成, + 任务结束到安全位, + 等待任务结束到安全位 + } + + + public class RearrangeFlow:BaseFlow + { + private static RearrangeFlow instance; + public static RearrangeFlow Instance + { + get + { + if (instance == null) + { + instance = new RearrangeFlow(); + } + return instance; + } + } + ERearrangeFlowStep flowStep = ERearrangeFlowStep.等待任务; + Nozzle curNozzle; + TurnoverInfo curTask; + SlotPoint curSlotPoint; + SlotPoint nozzleDist; + double targetX = 0.0; + double targetY = 0.0; + int FetchNum = 0;//取料次数 + ErrorCode errCode = ErrorCode.Ok; + public override void Run() + { + switch (flowStep) + { + case ERearrangeFlowStep.等待任务: + if (RearrangeTask.HasTask() && WorkEnvironment.Instance.EnvironmentOk) + { + WorkFlow.Instance.Stop(); + logInfo = $"接收重排任务"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.到取料位上方; + } + break; + case ERearrangeFlowStep.到取料位上方: + curTask = RearrangeTask.GetTask(); + curNozzle = NozzleManager.GetIdelNozzle(); + if (curTask != null && curNozzle != null) + { + if (SafeControl.Instance.XYCanMove() || GlobalVar.VirtualAxis) + { + curSlotPoint = null; + string traytype = "OK"; + switch (curTask.FromType) + { + case TurnoverType.Passed: + traytype = "OK"; + break; + case TurnoverType.Failed: + traytype = "NG"; + break; + case TurnoverType.Multifunction: + traytype = "Multi"; + break; + default: + break; + } + logInfo = $"吸嘴{curNozzle.NozzleIndex} 去{traytype}盘 {curTask.FromIndex+1} 号穴位取料"; + curSlotPoint = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, traytype, curTask.FromIndex+1, EPointType.BASE); + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + if (curSlotPoint != null) + { + nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex); + targetX = curSlotPoint.X + nozzleDist.X; + targetY = curSlotPoint.Y + nozzleDist.Y; + errCode = AxisControl.LoadX.MovePos(targetX, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + errCode = AxisControl.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue($"NozzleR{curNozzle.NozzleIndex}StartPos"), (int)(GlobalVar.WholeSpeed)); + errCode = AxisControl.LoadY.MovePos(targetY, (int)(GlobalVar.WholeSpeed)); + if (errCode == ErrorCode.Ok | GlobalVar.VirtualAxis) + { + flowStep = ERearrangeFlowStep.等待到取料位上方; + } + } + } + } + else + { + logInfo = "x y move isn't safe"; + Msg.ShowError(logInfo); + LogHelper.Error(logInfo); + MessageQueue.Instance.Warn(logInfo); + } + } + + break; + case ERearrangeFlowStep.等待到取料位上方: + if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis) + { + logInfo = "已运动到取料位上方"; + Thread.Sleep(100); + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.到取料位下方; + + } + break; + case ERearrangeFlowStep.到取料位下方: + if (GlobalVar.VirtualAxis) + { + Thread.Sleep(GlobalVar.VirtualAxisMoveTime); + flowStep = ERearrangeFlowStep.等待到取料位下方; + } + else + { + if (AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").HomeStatus == EHomeStatus.Finished) + { + logInfo = "准备运动到取料位下方"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(GetVacOffsetHeight(FetchNum) + SysConfigParam.GetValue($"TrayNozzle{curNozzle.NozzleIndex}TakeHeight"), GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok) + { + flowStep = ERearrangeFlowStep.等待到取料位下方; + } + } + else + { + logInfo = $"NozzleZ{curNozzle.NozzleIndex} 不在原点,请手动回原后点击确定"; + Msg.ShowError(logInfo); + LogHelper.Error(logInfo); + } + } + + break; + case ERearrangeFlowStep.等待到取料位下方: + if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis) + { + logInfo = "已运动到取料位下方"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.开真空; + } + break; + case ERearrangeFlowStep.开真空: + if (GlobalVar.VirtualAxis) + { + flowStep = ERearrangeFlowStep.取料完成抬起; + } + else + { + Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀"); + Thread.Sleep(GlobalVar.LoadNozzleOpenVacSuctionDelaytime); + logInfo = $"打开{curNozzle.NozzleIndex}号吸嘴真空吸"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.取料完成抬起; + } + + break; + + case ERearrangeFlowStep.取料完成抬起: + errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + logInfo = "取料完成准备抬起"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.等待取料完成抬起; + } + break; + case ERearrangeFlowStep.等待取料完成抬起: + if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis) + { + logInfo = "取料完成已运动到抬起位,准备真空检测"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.取料真空检测; + } + break; + case ERearrangeFlowStep.取料真空检测: + if (Ops.IsOn($"{curNozzle.NozzleIndex}号吸嘴真空吸检测") || GlobalVar.RunSpace || GlobalVar.VirtualAxis) + { + FetchNum = 0; + logInfo = $"吸嘴{curNozzle.NozzleIndex}真空检测 OK"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + + curNozzle.Status = ENozzleStatus.ToUnload; + curNozzle.FromType = curTask.FromType; + curNozzle.ToType = curTask.ToType; + curNozzle.ToIndex = curTask.ToIndex; + curTask.SuckerNo = curNozzle.NozzleIndex; + curNozzle.TurnoverGUID = curTask.GUID; + if (curTask.FromType == TurnoverType.Passed) + { + curNozzle.FromFloor = StockManager.Instance.GetTray(EStockType.Ok).GetFloor(); + curNozzle.SN = ""; + curNozzle.FromIndex = curTask.FromIndex; + GlobalTray.OkTary.ChangeStatus(curNozzle.FromIndex+1, ESlotStatus.NotHave); + } + else if (curTask.FromType == TurnoverType.Failed) + { + curNozzle.FromFloor = StockManager.Instance.GetTray(EStockType.Ng).GetFloor(); + curNozzle.SN = ""; + curNozzle.FromIndex = curTask.FromIndex; + GlobalTray.NgTray.ChangeStatus(curNozzle.FromIndex + 1, ESlotStatus.NotHave); + } + curNozzle.Update(); + curTask.Dealed = true; + if (RearrangeTask.HasTask() && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0) + { + logInfo = $"检测到还有条任务未执行,继续执行"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.到取料位上方; + } + else + { + flowStep = ERearrangeFlowStep.到放料位上方; + } + } + else + { + //FetchNum++; + //if (FetchNum == 6) + //{ + // //DialogResult dr = Msg.ShowError($"吸嘴{curNozzle.NozzleIndex}取料{FetchNum}次失败报警,请处理后点击确定", MessageBoxButtons.RetryCancel); + // CloseResult cr = new TakeFailMsg().ShowMsg($"吸嘴{curNozzle.NozzleIndex}取料{FetchNum}次失败报警,请处理后点击确定"); + // if (cr.Result == ECloseButton.Retry) + // { + // FetchNum = 0; + // flowStep = ERearrangeFlowStep.到取料位下方; + // } + // else if (cr.Result == ECloseButton.Skip)//switch + // { + // FetchNum = 0; + // if (curTask.FromType == TurnoverType.Turnover) + // { + // GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex + 1, ESlotStatus.NotHave); + // } + // else if (curTask.FromType == TurnoverType.ToBeTested) + // { + // GlobalTray.InputTray.ChangeStatus(GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index, ESlotStatus.NotHave); + // } + // if (LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode) > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0) + // { + // flowStep = ERearrangeFlowStep.到取料位上方; + // } + // else + // { + // flowStep = ERearrangeFlowStep.到下相机拍照起始位; + // } + // } + // else if (cr.Result == ECloseButton.EndInput) + // { + // FetchNum = 0; + // TestCenter.Instance.EndInput(); + // LoadAndUnloadTask.Instance.ClearUndoTask(); + // if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0) + // { + // flowStep = ERearrangeFlowStep.到下相机拍照起始位; + // } + // else + // { + // flowStep = ERearrangeFlowStep.任务结束到安全位; + // } + // } + // else if (cr.Result == ECloseButton.Continue) + // { + // FetchNum = 0; + // curNozzle.Status = ENozzleStatus.ToUnload; + // curNozzle.FromType = curTask.FromType; + // curNozzle.FromFloor = curTask.FromFloor; + + // curNozzle.ToType = curTask.ToType; + // curNozzle.ToIndex = curTask.ToIndex; + // curTask.SuckerNo = curNozzle.NozzleIndex; + // curNozzle.TurnoverGUID = curTask.GUID; + // if (curTask.FromType == TurnoverType.Turnover) + // { + // curNozzle.SN = curTask.SN; + // curNozzle.FromIndex = curTask.FromIndex; + // GlobalTray.TurnoverTray.ChangeStatus(curTask.FromIndex + 1, ESlotStatus.NotHave); + // } + // else if (curTask.FromType == TurnoverType.ToBeTested) + // { + // curNozzle.FromIndex = GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index; + // GlobalTray.InputTray.ChangeStatus(GlobalTray.InputTray.GetSlot(ESlotStatus.Have).Index, ESlotStatus.NotHave); + // } + // curNozzle.Update(); + // curTask.Dealed = true; + // if (LoadAndUnloadTask.Instance.GetTaskNum(curTask.taskMode) > 0 && NozzleManager.GetNozzlesByStatus(ENozzleStatus.IDLE).Count > 0) + // { + // flowStep = ERearrangeFlowStep.到取料位上方; + // } + // else + // { + // if (GlobalVar.VirtualAxis) + // { + // foreach (Nozzle nl in NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload)) + // { + // if (string.IsNullOrEmpty(nl.SN)) + // nl.SN = nl.FromIndex.ToString().PadLeft(18, '0'); + // //nl.SN = GuidHelper.Create(); + // } + // mrs = new List(); + // for (int i = 0; i < needGrabNum; i++) + // { + // mrs.Add(new MatchResult()); + // } + // flowStep = ERearrangeFlowStep.到放料位上方; + // } + // else + // { + // flowStep = ERearrangeFlowStep.到下相机拍照起始位; + // } + + // } + // } + //} + //else + //{ + // flowStep = ERearrangeFlowStep.到取料位下方; + //} + } + break; + case ERearrangeFlowStep.到放料位上方: + if (SafeControl.Instance.XYCanMove() || GlobalVar.VirtualAxis) + { + targetX = 0.0; + targetY = 0.0; + ///获取需要放料的吸嘴 + curSlotPoint = null; + curNozzle = NozzleManager.GetToUnloadNozzle(); + if (curNozzle != null) + { + curSlotPoint = GetSlotPoint(curNozzle.ToType); + } + if (curSlotPoint != null) + { + nozzleDist = TrayPointManager.GetDistToNozzle1(curNozzle.NozzleIndex); + targetX = curSlotPoint.X + nozzleDist.X; + targetY = curSlotPoint.Y + nozzleDist.Y; + errCode = AxisControl.LoadX.MovePos(targetX, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + errCode = AxisControl.LoadY.MovePos(targetY, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + errCode = AxisControl.GetAxis($"NozzleR{curNozzle.NozzleIndex}").MoveOffset(0, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + flowStep = ERearrangeFlowStep.等待到放料位上方; + } + } + } + } + } + else + { + Msg.ShowError("x y move isn't safe"); + } + break; + case ERearrangeFlowStep.等待到放料位上方: + if (Ops.IsStop("LoadX", "LoadY", $"NozzleR{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis) + { + Thread.Sleep(100); + logInfo = "已运动到放料位上方"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.到放料位下方; + + } + break; + case ERearrangeFlowStep.到放料位下方: + logInfo = "到放料位下方"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(SysConfigParam.GetValue($"TurnoverNozzle{curNozzle.NozzleIndex}TakeHeight") + 3, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + flowStep = ERearrangeFlowStep.等待到放料位下方; + } + break; + case ERearrangeFlowStep.等待到放料位下方: + if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis) + { + logInfo = "已运动到放料位下方"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空吸电磁阀"); + Thread.Sleep(GlobalVar.LoadNozzleCloseVacSuctionDelaytime); + Ops.On($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀"); + Thread.Sleep(GlobalVar.LoadNozzleOpenVacBreakDelaytime); + Ops.Off($"{curNozzle.NozzleIndex}号吸嘴真空破电磁阀"); + Thread.Sleep(GlobalVar.LoadNozzleCloseVacBreakDelaytime); + flowStep = ERearrangeFlowStep.放料完成抬起; + + } + break; + case ERearrangeFlowStep.放料完成抬起: + errCode = AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").MovePos(0, GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + logInfo = "放料完成抬起"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.等待放料完成抬起; + } + break; + case ERearrangeFlowStep.等待放料完成抬起: + if (Ops.IsStop($"NozzleZ{curNozzle.NozzleIndex}") || GlobalVar.VirtualAxis) + { + logInfo = "放料完成已运动到抬起位,准备真空检测"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + flowStep = ERearrangeFlowStep.放料真空检测; + } + break; + case ERearrangeFlowStep.放料真空检测: + flowStep = ERearrangeFlowStep.放料任务完成; + break; + case ERearrangeFlowStep.放料任务完成: + logInfo = "放料任务完成"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + AxisControl.GetAxis($"NozzleZ{curNozzle.NozzleIndex}").Home(); + if (curNozzle.ToType == TurnoverType.Passed) + { + GlobalTray.OkTary.ChangeStatus(curNozzle.ToIndex+1, ESlotStatus.Have); + } + else if (curNozzle.ToType == TurnoverType.Failed) + { + GlobalTray.NgTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have); + } + else if (curNozzle.ToType == TurnoverType.Multifunction) + { + GlobalTray.MultiTray.ChangeStatus(curNozzle.ToIndex + 1, ESlotStatus.Have); + } + curNozzle.Reset(); + Thread.Sleep(100); + RearrangeTask.AddWaitReportTask(curNozzle); + if (NozzleManager.GetNozzlesByStatus(ENozzleStatus.ToUnload).Count > 0) + { + flowStep = ERearrangeFlowStep.到放料位上方; + } + else + { + if (RearrangeTask.HasTask()) + { + flowStep = ERearrangeFlowStep.到取料位上方; + } + else + { + flowStep = ERearrangeFlowStep.任务结束到安全位; + } + } + break; + + case ERearrangeFlowStep.任务结束到安全位: + logInfo = "任务结束到安全位"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + errCode = AxisControl.LoadX.MovePos(SysConfigParam.GetValue("LoadXStartPos"), GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + errCode = AxisControl.LoadY.MovePos(SysConfigParam.GetValue("LoadYStartPos"), GlobalVar.WholeSpeed); + if (errCode == ErrorCode.Ok || GlobalVar.VirtualAxis) + { + flowStep = ERearrangeFlowStep.等待任务结束到安全位; + } + } + break; + case ERearrangeFlowStep.等待任务结束到安全位: + if (Ops.IsStop("LoadX", "LoadY") || GlobalVar.VirtualAxis) + { + logInfo = "任务结束已回到安全位"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + if (RearrangeTask.ReportCenter()>0) + { + logInfo = "通知中控任务完成"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + + RearrangeTask.RemoveAll(); + logInfo = "任务完成,清除任务"; + MessageQueue.Instance.Insert(logInfo); + LogHelper.Debug(logInfo); + } + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); + flowStep = ERearrangeFlowStep.等待任务; + } + break; + default: + break; + } + } + + private double GetVacOffsetHeight(int fetchNum) + { + switch (fetchNum) + { + case 0: + return 0; + case 1: + return -0.1; + case 2: + return -0.2; + case 3: + return -0.3; + case 4: + return 0.1; + case 5: + return 0.2; + case 6: + return 0.3; + default: + return 0; + } + } + + private SlotPoint GetSlotPoint(TurnoverType trayType) + { + SlotPoint pt = new SlotPoint(); + switch (trayType) + { + case TurnoverType.Passed: + logInfo = "到Pass盘放料位上方"; + pt = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "OK", curNozzle.ToIndex + 1, EPointType.RUN); + break; + case TurnoverType.Failed: + logInfo = "到Ng盘放料位上方"; + pt = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "NG", curNozzle.ToIndex + 1, EPointType.RUN); + break; + case TurnoverType.Multifunction: + logInfo = "到Multi盘放料位上方"; + pt = TrayPointManager.GetSlotPoint(GlobalVar.CurRecipe, "Multi", curNozzle.ToIndex + 1, EPointType.RUN); + break; + default: + break; + } + return pt; + } + } +} diff --git a/Rs.SkyLine/Flow/RearrangeTask.cs b/Rs.SkyLine/Flow/RearrangeTask.cs new file mode 100644 index 0000000..04c4810 --- /dev/null +++ b/Rs.SkyLine/Flow/RearrangeTask.cs @@ -0,0 +1,66 @@ +using Rs.MotionPlat.Commom; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rs.MotionPlat.Flow +{ + public static class RearrangeTask + { + private static List rearrangeTasks = new List(); + private static List waitReportList = new List(); + public static void Add(TurnoverInfo task) + { + rearrangeTasks.Add(task); + } + + public static void AddRanage(List tasks) + { + rearrangeTasks.AddRange(tasks); + } + + public static bool HasTask() + { + return rearrangeTasks.Where(t=>t.Dealed==false).Count() > 0; + } + + public static TurnoverInfo GetTask() + { + return rearrangeTasks.Where(t => t.Dealed == false).First(); + } + + public static void RemoveAll() + { + rearrangeTasks.Clear(); + waitReportList.Clear(); + } + + public static void AddWaitReportTask(Nozzle nozzle) + { + TurnoverInfo turnoverInfo = new TurnoverInfo(); + turnoverInfo.FromType = nozzle.FromType; + turnoverInfo.FromFloor = nozzle.FromFloor; + turnoverInfo.FromIndex = nozzle.FromIndex; + turnoverInfo.ToType = nozzle.ToType; + turnoverInfo.ToFloor = nozzle.ToFloor; + turnoverInfo.ToIndex = nozzle.ToIndex; + turnoverInfo.SN = nozzle.SN; + turnoverInfo.Dealed = true; + turnoverInfo.SuckerNo = nozzle.NozzleIndex; + waitReportList.Add(turnoverInfo); + } + + + public static int ReportCenter() + { + TurnoverInfos infos = new TurnoverInfos(); + infos.TurnoverID = 0; + infos.GroupID = 0; + infos.Instruction = EInstruction.RearrangeResult; + infos.Infos = waitReportList; + return TestCenter.Instance.Send(infos); + } + } +} diff --git a/Rs.SkyLine/Flow/SafeControl.cs b/Rs.SkyLine/Flow/SafeControl.cs index 7b34a98..0bb7e20 100644 --- a/Rs.SkyLine/Flow/SafeControl.cs +++ b/Rs.SkyLine/Flow/SafeControl.cs @@ -75,5 +75,24 @@ namespace Rs.MotionPlat.Flow } return true; } + + /// + /// 检测排料Y轴是否可以到周转盘 + /// + /// + private bool CanGoTurnoverTray() + { + //获取周转Y轴的位置,当排料Y轴去周转盘的时候,检测是否安全 + double turnoverYPos = Ops.GetCurPosition("TurnoverY"); + if (turnoverYPos - SysConfigParam.GetValue("PressY") < -1) + return false; + return true; + } + public bool XYCanMove() + { + if (!CanGoTurnoverTray()) + return false; + return true; + } } } diff --git a/Rs.SkyLine/Flow/Space/TrayTest.cs b/Rs.SkyLine/Flow/Space/TrayTest.cs index 4dcfc27..5a82e7d 100644 --- a/Rs.SkyLine/Flow/Space/TrayTest.cs +++ b/Rs.SkyLine/Flow/Space/TrayTest.cs @@ -92,17 +92,6 @@ namespace Rs.AutoDischarge.V3.Flow stockNo = _stockNo; StockFlow = AxisControl.GetAxis($"StockFlow{stockNo}"); StockZ = AxisControl.GetAxis($"StockZ{stockNo}"); - switch (stockNo) - { - case 1:tray = GlobalTray.Empty1Tray;break; - case 2: tray = GlobalTray.InputTray; break; - case 3: tray = GlobalTray.OkTary; break; - case 4: tray = GlobalTray.NgTray; break; - case 5: tray = GlobalTray.MultiTray; break; - case 6: tray = GlobalTray.Empty2Tray; break; - default: - break; - } //baseHeight = GlobalVar.Instance.GetValue($"Stock{stockNo}BaseHeight"); //trayHeight = GlobalVar.Instance.GetValue("TrayHeight"); } @@ -123,17 +112,28 @@ namespace Rs.AutoDischarge.V3.Flow { if (NeedUnload) { - logInfo = $"{GetTrayName()} 料仓收到下料任务"; - MessageQueue.Instance.Insert(logInfo); - Status = ETrayStatus.Unloading; - //下料 - IoManager.Instance.WriteOut($"{stockNo}号料仓斜推气缸", 0); - Thread.Sleep(200); - finished = false; - NeedUnload = false; - ReportSwitchTray(stockNo); + //判断是否有料盘 + if(StockManager.Instance.HasTray(stockNo)) + { + logInfo = $"{GetTrayName()} 料仓收到下料任务"; + MessageQueue.Instance.Insert(logInfo); + Status = ETrayStatus.Unloading; + //下料 + IoManager.Instance.WriteOut($"{stockNo}号料仓斜推气缸", 0); + Thread.Sleep(200); + finished = false; + NeedUnload = false; + ReportSwitchTray(stockNo); - Step = ETrayTestStep.到下料降速位; + Step = ETrayTestStep.到下料降速位; + } + else + { + NeedLoad = false; + StockManager.Instance.ResetStock(stockNo); + Status = ETrayStatus.Unloaded; + finished = true; + } } else if (NeedLoad) @@ -235,38 +235,7 @@ namespace Rs.AutoDischarge.V3.Flow case ETrayTestStep.等待下料完成回原点: if (Ops.IsStop($"StockZ{stockNo}") || GlobalVar.VirtualAxis) { - switch(stockNo) - { - case 1: - GlobalTray.Empty1Tray.ResetTray(); - GlobalTray.Empty1Tray.Clear(); - break; - - case 2: - GlobalTray.InputTray.ResetTray(); - GlobalTray.InputTray.Clear(); - break; - - case 3: - GlobalTray.OkTary.ResetTray(); - GlobalTray.OkTary.Clear(); - break; - - case 4: - GlobalTray.NgTray.ResetTray(); - GlobalTray.NgTray.Clear(); - break; - - case 5: - GlobalTray.MultiTray.ResetTray(); - GlobalTray.MultiTray.Clear(); - break; - - case 6: - GlobalTray.Empty2Tray.ResetTray(); - GlobalTray.Empty2Tray.Clear(); - break; - } + StockManager.Instance.ResetStock(stockNo); Status = ETrayStatus.Unloaded; finished = true; Step = ETrayTestStep.等待命令; diff --git a/Rs.SkyLine/Flow/StockManager.cs b/Rs.SkyLine/Flow/StockManager.cs index 3d95935..fb7d336 100644 --- a/Rs.SkyLine/Flow/StockManager.cs +++ b/Rs.SkyLine/Flow/StockManager.cs @@ -92,6 +92,16 @@ namespace Rs.MotionPlat.Flow return true; } + public bool HasTray(int stockNo) + { + + if (Ops.IsOff($"{stockNo}号料仓料盘到位光电检测")) + { + return false; + } + return true; + } + public TrayTest GetTray(EStockType stockType) { @@ -247,5 +257,60 @@ namespace Rs.MotionPlat.Flow break; } } + + public void ResetStock(EStockType stock) + { + switch (stock) + { + case EStockType.Empty1: + break; + case EStockType.Input: + break; + case EStockType.Ok: + break; + case EStockType.Ng: + break; + case EStockType.Multi: + break; + case EStockType.Empty2: + break; + } + } + + public void ResetStock(int stockNo) + { + switch (stockNo) + { + case 1: + GlobalTray.Empty1Tray.ResetTray(); + GlobalTray.Empty1Tray.Clear(); + break; + + case 2: + GlobalTray.InputTray.ResetTray(); + GlobalTray.InputTray.Clear(); + break; + + case 3: + GlobalTray.OkTary.ResetTray(); + GlobalTray.OkTary.Clear(); + break; + + case 4: + GlobalTray.NgTray.ResetTray(); + GlobalTray.NgTray.Clear(); + break; + + case 5: + GlobalTray.MultiTray.ResetTray(); + GlobalTray.MultiTray.Clear(); + break; + + case 6: + GlobalTray.Empty2Tray.ResetTray(); + GlobalTray.Empty2Tray.Clear(); + break; + } + } } } diff --git a/Rs.SkyLine/Flow/TestCenter.cs b/Rs.SkyLine/Flow/TestCenter.cs index e47f836..8f6ea6e 100644 --- a/Rs.SkyLine/Flow/TestCenter.cs +++ b/Rs.SkyLine/Flow/TestCenter.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Rs.AutoDischarge.V3.Flow; +using Rs.Controls; using Rs.Framework; using Rs.MotionPlat.Commom; using System; @@ -40,7 +41,20 @@ namespace Rs.MotionPlat.Flow case SchedulingStatusInfo.InfoType.State: break; case SchedulingStatusInfo.InfoType.RunStatus: - Ops.Start(); + if(ssi.Info== "Started") + { + MachineManage.Instance.SetCenterMachineStatus(ERunStatus.Started); + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Interrupt); + MessageQueue.Instance.Insert("收到中控启动命令"); + LogHelper.Debug("收到中控启动命令"); + Ops.Start(); + } + else if(ssi.Info== "Stopped") + { + MessageQueue.Instance.Insert("收到中控停止命令"); + LogHelper.Debug("收到中控停止命令"); + Ops.Stop(); + } //WorkEnvironment.Instance.Ready(); //Task.Run(() => { // if (WorkEnvironment.Instance.EnvReadyOkEvent.WaitOne()) @@ -51,8 +65,8 @@ namespace Rs.MotionPlat.Flow // MachineManage.Instance.MachineStatus = EMachineStatus.Working; // } //}); - MachineManage.Instance.RunStatus = ERunStatus.Started; - MachineManage.Instance.RunState = ERunState.Interrupt; + //MachineManage.Instance.RunStatus = ERunStatus.Started; + //MachineManage.Instance.RunState = ERunState.Interrupt; break; case SchedulingStatusInfo.InfoType.RunMode://手动自动 MachineManage.Instance.RunMode = (ERunMode)Enum.Parse(typeof(ERunMode), ssi.Info.ToString()); @@ -112,12 +126,12 @@ namespace Rs.MotionPlat.Flow switch (statusInto.Type) { case SchedulingStatusInfo.InfoType.State: - statusInto.Info = MachineManage.Instance.RunState.ToString();// ERunState.Waiting.ToString(); + statusInto.Info = MachineManage.Instance.GetLoadUnloadStatus().ToString();// ERunState.Waiting.ToString(); //MessageQueue.Instance.Insert(statusInto.Info); //File.AppendAllText("c://runstate.txt",statusInto.Info.ToString()+"\r\n"); break; case SchedulingStatusInfo.InfoType.RunStatus: - statusInto.Info = MachineManage.Instance.RunStatus.ToString();// ERunStatus.Started.ToString(); + statusInto.Info = MachineManage.Instance.GetCenterRunStatus().ToString();// ERunStatus.Started.ToString(); break; case SchedulingStatusInfo.InfoType.RunMode: statusInto.Info = MachineManage.Instance.RunMode.ToString(); @@ -197,10 +211,6 @@ namespace Rs.MotionPlat.Flow break; case EInstruction.CancelAlarms: break; - case EInstruction.IsLastBeforeTray: - break; - case EInstruction.EndInput: - break; case EInstruction.TakingError: break; case EInstruction.CancelTakingError: @@ -224,25 +234,59 @@ namespace Rs.MotionPlat.Flow /// private void Rearrange(string json) { - MachineManage.Instance.RunState = ERunState.Busying; + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Busying); SiloRearrange info = JsonConvert.DeserializeObject(json); - Send(info); - - - Thread.Sleep(2000); - - TurnoverInfos tis = new TurnoverInfos(); - tis.GroupID = 0; - tis.Instruction = EInstruction.RearrangeResult; - Send(tis); - MachineManage.Instance.RunState = ERunState.Waiting; + if(info.SiloType== SchedulingSiloBase.ESiloType.Multifunction) + { + TurnoverInfos tis = new TurnoverInfos(); + tis.GroupID = 0; + tis.Instruction = EInstruction.RearrangeResult; + Send(tis); + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); + } + else if(info.SiloType== SchedulingSiloBase.ESiloType.Passed) + { + TraySlot ts = GlobalTray.OkTary.GetSlot(Controls.ESlotStatus.NotHave); + if((ts.Index-1)%10==0) + { + TurnoverInfos tis = new TurnoverInfos(); + tis.GroupID = 0; + tis.Instruction = EInstruction.RearrangeResult; + Send(tis); + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); + } + else + { + List rearrangeList = RearrangeManager.GeneralRearrangeTask(TurnoverType.Passed, ts.Index-1, StockManager.Instance.GetTray(EStockType.Ok).GetFloor()); + RearrangeTask.AddRanage(rearrangeList); + RearrangeFlow.Instance.Start(); + } + } + else if (info.SiloType == SchedulingSiloBase.ESiloType.Failed) + { + TraySlot ts = GlobalTray.NgTray.GetSlot(ESlotStatus.NotHave); + if ((ts.Index-1) % 10 == 0) + { + TurnoverInfos tis = new TurnoverInfos(); + tis.GroupID = 0; + tis.Instruction = EInstruction.RearrangeResult; + Send(tis); + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); + } + else + { + List rearrangeList = RearrangeManager.GeneralRearrangeTask(TurnoverType.Failed, ts.Index-1, StockManager.Instance.GetTray(EStockType.Ng).GetFloor()); + RearrangeTask.AddRanage(rearrangeList); + RearrangeFlow.Instance.Start(); + } + } } private void LoadAndUnload(string json) { LogHelper.Debug("recive:" + json); - MachineManage.Instance.RunState = ERunState.Busying; + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Busying); sm = JsonConvert.DeserializeObject(json); schedulResult = new SchedulingResult() { Instruction = sm.Instruction, State = ERunState.Busying, GroupID = sm.GroupID, TurnoverID = sm.TurnoverID }; string buffer = schedulResult.ToString(); @@ -272,6 +316,7 @@ namespace Rs.MotionPlat.Flow switch (inquireSilo.SiloType) { case SchedulingSiloBase.ESiloType.ToBeTested: + inquireSilo.SiloStatus = TranlateSiloStatus(StockManager.Instance.GetStockStatus(EStockType.Input)); break; case SchedulingSiloBase.ESiloType.Passed: @@ -312,28 +357,32 @@ namespace Rs.MotionPlat.Flow private void RequestSwitchTray(string json) { SchedulingSilo inquireSilo = JsonConvert.DeserializeObject(json); - switch (inquireSilo.SiloType) + if(inquireSilo.Orientation== ESwitchOrientation.Recycle) { - case SchedulingSiloBase.ESiloType.ToBeTested: - StockManager.Instance.UnLoad(EStockType.Input); - break; - case SchedulingSiloBase.ESiloType.Passed: - StockManager.Instance.UnLoad(EStockType.Ok); - break; - case SchedulingSiloBase.ESiloType.Failed: - StockManager.Instance.UnLoad(EStockType.Ng); - break; - case SchedulingSiloBase.ESiloType.Multifunction: - StockManager.Instance.UnLoad(EStockType.Multi); - break; - case SchedulingSiloBase.ESiloType.EmptyInput: - StockManager.Instance.UnLoad(EStockType.Empty1); - break; - case SchedulingSiloBase.ESiloType.EmptyOutput: - StockManager.Instance.UnLoad(EStockType.Empty2); - break; + switch (inquireSilo.SiloType) + { + case SchedulingSiloBase.ESiloType.ToBeTested: + MessageQueue.Instance.Insert("Input料仓收到切盘命令"); + StockManager.Instance.UnLoad(EStockType.Input); + break; + case SchedulingSiloBase.ESiloType.Passed: + StockManager.Instance.UnLoad(EStockType.Ok); + break; + case SchedulingSiloBase.ESiloType.Failed: + StockManager.Instance.UnLoad(EStockType.Ng); + break; + case SchedulingSiloBase.ESiloType.Multifunction: + StockManager.Instance.UnLoad(EStockType.Multi); + break; + case SchedulingSiloBase.ESiloType.EmptyInput: + StockManager.Instance.UnLoad(EStockType.Empty1); + break; + case SchedulingSiloBase.ESiloType.EmptyOutput: + StockManager.Instance.UnLoad(EStockType.Empty2); + break; + } + Send(inquireSilo); } - Send(inquireSilo); } /// diff --git a/Rs.SkyLine/Flow/WorkFlow.cs b/Rs.SkyLine/Flow/WorkFlow.cs index 0ad0726..b656919 100644 --- a/Rs.SkyLine/Flow/WorkFlow.cs +++ b/Rs.SkyLine/Flow/WorkFlow.cs @@ -1073,7 +1073,7 @@ namespace Rs.MotionPlat.Flow MessageQueue.Instance.Insert(logInfo); LogHelper.Debug(logInfo); } - MachineManage.Instance.RunState = ERunState.Waiting; + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); flowStep = EWorkFlowStep.等待任务; } break; @@ -1092,7 +1092,7 @@ namespace Rs.MotionPlat.Flow GlobalTray.TurnoverTray.ChangeStatus(turnoverInfo.FromIndex+1, ESlotStatus.NotHave); } LoadAndUnloadTask.Instance.Clear(); - MachineManage.Instance.RunState = ERunState.Waiting; + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); //for (int i = 1; i < 9; i++) //{ @@ -1130,7 +1130,7 @@ namespace Rs.MotionPlat.Flow //{ // GlobalTray.TurnoverTray.ChangeStatus(i, ESlotStatus.Have); //} - MachineManage.Instance.RunState = ERunState.Waiting; + MachineManage.Instance.SetLoadUnloadStatus(ERunState.Waiting); flowStep = EWorkFlowStep.等待任务; } break; diff --git a/Rs.SkyLine/Rs.SkyLine.csproj b/Rs.SkyLine/Rs.SkyLine.csproj index 2f12ce9..15f160c 100644 --- a/Rs.SkyLine/Rs.SkyLine.csproj +++ b/Rs.SkyLine/Rs.SkyLine.csproj @@ -161,6 +161,8 @@ + + diff --git a/Rs.SkyLine/SysConfig/CommonConfig.Designer.cs b/Rs.SkyLine/SysConfig/CommonConfig.Designer.cs index 9b48568..e909206 100644 --- a/Rs.SkyLine/SysConfig/CommonConfig.Designer.cs +++ b/Rs.SkyLine/SysConfig/CommonConfig.Designer.cs @@ -59,6 +59,8 @@ this.label18 = new System.Windows.Forms.Label(); this.textBox10 = new System.Windows.Forms.TextBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cboxOrderByLeftToRight = new System.Windows.Forms.CheckBox(); + this.cboxVirtualAxis = new System.Windows.Forms.CheckBox(); this.cboxCheckSafeEnable = new System.Windows.Forms.CheckBox(); this.cboxRunSpace = new System.Windows.Forms.CheckBox(); this.panelEx1 = new Rs.Controls.PanelEx(); @@ -136,7 +138,7 @@ this.groupBox3.Size = new System.Drawing.Size(778, 433); this.groupBox3.TabIndex = 2; this.groupBox3.TabStop = false; - this.groupBox3.Text = "参数设定"; + this.groupBox3.Text = "相机参数设定"; // // txtDownCameraFlyRegrabNum // @@ -484,6 +486,8 @@ // // groupBox1 // + this.groupBox1.Controls.Add(this.cboxOrderByLeftToRight); + this.groupBox1.Controls.Add(this.cboxVirtualAxis); this.groupBox1.Controls.Add(this.cboxCheckSafeEnable); this.groupBox1.Controls.Add(this.cboxRunSpace); this.groupBox1.Controls.Add(this.panelEx1); @@ -520,6 +524,26 @@ this.groupBox1.TabStop = false; this.groupBox1.Text = "参数设定"; // + // cboxOrderByLeftToRight + // + this.cboxOrderByLeftToRight.AutoSize = true; + this.cboxOrderByLeftToRight.Location = new System.Drawing.Point(323, 341); + this.cboxOrderByLeftToRight.Name = "cboxOrderByLeftToRight"; + this.cboxOrderByLeftToRight.Size = new System.Drawing.Size(96, 16); + this.cboxOrderByLeftToRight.TabIndex = 8; + this.cboxOrderByLeftToRight.Text = "从左到右排料"; + this.cboxOrderByLeftToRight.UseVisualStyleBackColor = true; + // + // cboxVirtualAxis + // + this.cboxVirtualAxis.AutoSize = true; + this.cboxVirtualAxis.Location = new System.Drawing.Point(257, 341); + this.cboxVirtualAxis.Name = "cboxVirtualAxis"; + this.cboxVirtualAxis.Size = new System.Drawing.Size(60, 16); + this.cboxVirtualAxis.TabIndex = 8; + this.cboxVirtualAxis.Text = "虚拟轴"; + this.cboxVirtualAxis.UseVisualStyleBackColor = true; + // // cboxCheckSafeEnable // this.cboxCheckSafeEnable.AutoSize = true; @@ -900,5 +924,7 @@ private System.Windows.Forms.TrackBar tbarPressLowSpeed; private System.Windows.Forms.Label lblPressLowSpeed; private System.Windows.Forms.Label label20; + private System.Windows.Forms.CheckBox cboxVirtualAxis; + private System.Windows.Forms.CheckBox cboxOrderByLeftToRight; } } \ No newline at end of file diff --git a/Rs.SkyLine/SysConfig/QifuConfig.cs b/Rs.SkyLine/SysConfig/QifuConfig.cs index 4c3198d..b1935fa 100644 --- a/Rs.SkyLine/SysConfig/QifuConfig.cs +++ b/Rs.SkyLine/SysConfig/QifuConfig.cs @@ -1,4 +1,5 @@ -using Rs.Controls; +using Newtonsoft.Json.Linq; +using Rs.Controls; using Rs.MotionPlat.Commom; using System; using System.Collections.Generic;