using System; using SimpleCore.Library; using SimpleLite.RCS.CarTypes; using StandardScene.Signal.Model; using StandardScene.Signal.Plc; namespace StandardScene.Signal.Logic { /// /// 销钉 / 牵引棒升降后再放行。对齐反编译 DefaultPlugin.PointControl。 /// /// /// SignalParams动作;机构名。 /// 动作:UP1 升销钉1,UP2 升销钉1+2,Down1 / Down2 对应下降。 /// 机构名可选:填了则必须等该机构读字节=允许离开才启动;空则只等销钉动作完成。 /// 销钉指令通过 反射调用车体 MethodMember(如 SetPin1Up)。 /// public static class PointControlHandler { /// 停稳:先判机构是否允许离开,再下发销钉,全部到位后启动。 public static void OnStopped(Car car, SignalStopSpec spec, Func find) { var action = spec.Part(0).Trim(); var jgName = spec.Part(1).Trim(); if (string.IsNullOrEmpty(action)) { Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)},读取配置特殊点名称为空", "SetPin", true); return; } var waitLeave = false; if (!string.IsNullOrEmpty(jgName)) { var rt = find(jgName); if (rt != null) { lock (rt.Sync) waitLeave = rt.ReadSignal != SignalReadValue.允许离开; } } var pos = SignalCarAdapter.PositionId(car); switch (action) { case "UP1": PinThenGo(car, pos, waitLeave, jgName, "SetPin1Up"); break; case "UP2": PinThenGo(car, pos, waitLeave, jgName, "SetPin1Up", "SetPin2Up"); break; case "Down1": PinThenGo(car, pos, waitLeave, jgName, "SetPin1Down"); break; case "Down2": PinThenGo(car, pos, waitLeave, jgName, "SetPin1Down", "SetPin2Down"); break; } } /// /// 任一销钉未完成则本拍只下发指令、不启动; /// 全部完成且(无需等离开 或 已允许离开)才 Start。 /// private static void PinThenGo(Car car, int pos, bool waitLeave, string jgName, params string[] actions) { var done = true; foreach (var a in actions) { if (!SignalCarAdapter.IsActionFinish(car, a)) done = false; } if (!done) { foreach (var a in actions) SignalCarAdapter.Control(car, a); return; } if (waitLeave) { Diagnosis.Log($"AGV{car.id}停在地标{pos},需要读取{jgName}工位的允许离开", "SetPin", true); return; } SignalCarAdapter.Start(car); Diagnosis.Log($"AGV{car.id}停在地标{pos},牵引棒动作到位,已通知AGV启动", "SetPin", true); } } }