Files
StandardSence/StandardScene.Signal/Logic/RateFlowHandler.cs
T

93 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using SimpleCore.Library;
using SimpleLite.RCS.CarTypes;
using StandardScene.Signal.Plc;
namespace StandardScene.Signal.Logic
{
/// <summary>
/// 区域车组限流。对齐反编译 <c>DefaultPlugin.RateFlowControl</c>。
/// </summary>
/// <remarks>
/// 独立握手类型 <c>RateFlowControl</c> 用分号:<c>区域;车组;限额;点1,点2</c>。
/// 挂在 JGControl 第三段时用短横:<c>区域-车组-限额-点1,点2</c>(因为前两段机构名/动作已经占用分号)。
/// 统计「站点列表上、同车组、且不是本车」的数量,小于限额才放行。
/// 解析异常时放行(return true),避免配错把产线卡死。
/// </remarks>
public static class RateFlowHandler
{
/// <summary>独立限流点:通过则停充并启动。</summary>
public static void OnStopped(Car car, SignalStopSpec spec, IDictionary<string, int> logByArea)
{
if (AllowPass(car, spec.SignalParams, logByArea, sep: ';'))
{
SignalCarAdapter.StopCharge(car);
SignalCarAdapter.Start(car);
}
}
/// <summary>JGControl 第三段限流,短横分隔。不通过时调用方应直接 return,不启动。</summary>
public static bool AllowPass(Car car, string rateFlowString, IDictionary<string, int> logByArea) =>
AllowPass(car, rateFlowString, logByArea, sep: '-');
/// <param name="sep">独立类型用 ';'JGControl 挂载用 '-'。</param>
private static bool AllowPass(Car car, string raw, IDictionary<string, int> logByArea, char sep)
{
try
{
var parts = (raw ?? "").Split(sep);
var area = parts.Length > 0 ? parts[0] : "";
var group = parts.Length > 1 ? parts[1] : "";
var limit = 0;
if (parts.Length > 2)
int.TryParse(parts[2], out limit);
var sites = new List<int>();
if (parts.Length > 3)
{
foreach (var s in parts[3].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
if (int.TryParse(s.Trim(), out var id))
sites.Add(id);
}
}
var others = SignalCarAdapter.CarsAt(sites)
.Where(x => x.id != car.id && string.Equals(SignalCarAdapter.GroupId(x), group, StringComparison.Ordinal))
.ToList();
var count = others.Count;
if (count < limit)
{
Diagnosis.Log(
$"限流区域{area}限制AGV组{group}流量{limit}辆AGV,当前停放{count},放行AGV{car.id}",
"RateFlow", true);
Note(logByArea, area, car, raw);
return true;
}
Diagnosis.Log(
$"限流区域{area}限制AGV组{group}流量{limit}辆AGV,当前停放{count},无法放行",
"RateFlow", true);
Note(logByArea, area, car, raw);
return false;
}
catch (Exception ex)
{
Diagnosis.Log($"处理区域限流业务异常:{ex.Message}", "RateFlow", true);
return true;
}
}
/// <summary>同一限流区域仅在「决策车号变化」时再打一条带原始参数的日志。</summary>
private static void Note(IDictionary<string, int> logByArea, string area, Car car, string raw)
{
if (logByArea == null) return;
var changed = !logByArea.TryGetValue(area, out var last) || last != car.id;
logByArea[area] = car.id;
if (changed)
Diagnosis.Log($"AGV{car.id}停在地标{SignalCarAdapter.PositionId(car)},配置参数:【{raw}】", "RateFlow", true);
}
}
}