using System;
using System.Collections.Generic;
using System.Linq;
using SimpleCore.Library;
using SimpleLite.RCS.CarTypes;
using StandardScene.Signal.Model;
using StandardScene.Signal.Plc;
namespace StandardScene.Signal.Logic
{
///
/// 机构进出站握手。对齐反编译 DefaultPlugin.JGControl / JGJudge / RequestIn / Arrived。
///
///
///
/// SignalParams 分号三段:机构名;动作;限流。
/// 动作 RequestIn(请求进入,配在机构口外等待点)或 Arrived(到位,配在机构内地标)。
/// 第三段可选,格式与独立限流不同:区域-车组-限额-点1,点2(短横分隔,见 )。
///
///
/// RequestIn 放行条件(需同时满足):PLC 读字节=允许进入、尚无请求进入车、写字节=无状态。
/// 下线机构额外要求 JgPointId 上没有其它车。通过后写「进入中」、记下 RequestInAgvNo、停充并启动。
///
///
/// 车已在跑但本车不是请求进入车、且 PLC 不是允许进入时,立即停车(停稳拍与行驶拍都会判)。
/// Arrived:若 InAgvNo 还不是本车,写「到位」、登记 InAgvNo、清空 RequestInAgvNo。
/// 之后的「离开中 / 已离开」由 PLC Worker 的 推进。
///
///
public static class JgControlHandler
{
/// 停稳:可选限流 → RequestIn 或 Arrived。
public static void OnStopped(Car car, SignalStopSpec spec, Func find, IDictionary rateFlowLog)
{
var jgName = spec.JgName;
var action = spec.Action;
var dockId = spec.DockId;
var rateFlow = spec.ExtraParams;
if (string.IsNullOrEmpty(jgName))
{
Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)},读取配置机构名称为空", "JGControl", true);
return;
}
if (!string.IsNullOrEmpty(rateFlow) && !RateFlowHandler.AllowPass(car, rateFlow, rateFlowLog))
{
Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)},限流禁止通行", "JGControl", true);
return;
}
if (string.Equals(action, "RequestIn", StringComparison.OrdinalIgnoreCase))
RequestIn(jgName, dockId, car, find);
else if (string.Equals(action, "Arrived", StringComparison.OrdinalIgnoreCase))
Arrived(jgName, dockId, car, find);
}
/// 行驶中只做 RequestIn 安全闸:未允许进入且不是本车占用请求槽则停车。
public static void OnMoving(Car car, SignalStopSpec spec, Func find)
{
var jgName = spec.JgName;
var action = spec.Action;
if (string.IsNullOrEmpty(jgName))
return;
if (string.Equals(action, "RequestIn", StringComparison.OrdinalIgnoreCase))
RequestInJudge(jgName, spec.DockId, car, find);
}
private static void RequestIn(string jgName, string dockId, Car car, Func find)
{
var rt = find(jgName, dockId);
if (rt == null)
{
Diagnosis.Log($"{jgName} 未能找到机构", "JGControl", true);
return;
}
lock (rt.Sync)
{
if (rt.ReadSignal == SignalReadValue.允许进入 &&
rt.RequestInAgvNo == 0 &&
rt.ReadWriteSignal == SignalWriteValue.无状态)
{
if (rt.Station.LineType is SignalLineType.单牵引下线机构 or SignalLineType.双牵引下线机构)
{
var inside = SignalCarAdapter.CarsAt(rt.Dock.JgPointId);
if (inside.Count > 0)
{
Diagnosis.Log(
$"{rt.DisplayName} 机构内有AGV【{string.Join(",", inside.Select(x => x.id))}】暂不放行AGV{car.id}",
"JGControl", true);
return;
}
}
Diagnosis.Log($"{rt.DisplayName} 机构允许进入,通知AGV{car.id}启动,通知机构AGV进入中", "JGControl", true);
rt.WriteSignal = SignalWriteValue.进入中;
rt.RequestInAgvNo = car.id;
SignalCarAdapter.StopCharge(car);
SignalCarAdapter.Start(car);
return;
}
if (rt.ReadSignal != SignalReadValue.允许进入 &&
rt.RequestInAgvNo != car.id &&
SignalCarAdapter.IsMoving(car))
{
SignalCarAdapter.Stop(car);
Diagnosis.Log($"{rt.DisplayName} 机构不允许进入,监控到AGV启动,暂停AGV{car.id}", "JGControl", true);
}
}
}
private static void RequestInJudge(string jgName, string dockId, Car car, Func find)
{
var rt = find(jgName, dockId);
if (rt == null)
{
Diagnosis.Log($"{jgName} 未能找到机构", "JGControl", true);
return;
}
lock (rt.Sync)
{
if (rt.ReadSignal != SignalReadValue.允许进入 &&
rt.RequestInAgvNo != car.id &&
SignalCarAdapter.IsMoving(car))
{
SignalCarAdapter.Stop(car);
Diagnosis.Log($"{rt.DisplayName} 机构不允许进入,监控到AGV启动,暂停AGV{car.id}", "JGControl", true);
}
}
}
private static void Arrived(string jgName, string dockId, Car car, Func find)
{
var rt = find(jgName, dockId);
if (rt == null)
{
Diagnosis.Log($"{jgName} 未能找到机构", "JGControl", true);
return;
}
lock (rt.Sync)
{
if (rt.InAgvNo == car.id)
return;
Diagnosis.Log($"AGV{car.id}已到达机构{rt.DisplayName}", "JGControl", true);
rt.WriteSignal = SignalWriteValue.到位;
rt.InAgvNo = car.id;
rt.RequestInAgvNo = 0;
}
}
}
}