磁导航1.0内部交管和信号交互
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using LessokajiWeaverUtilities.Utilities;
|
||||
using Newtonsoft.Json;
|
||||
using SimpleCore;
|
||||
using SimpleCore.Library;
|
||||
using SimpleLite.RCS;
|
||||
using StandardScene.Signal.Logic;
|
||||
using StandardScene.Signal.Model;
|
||||
using StandardScene.Signal.Ui;
|
||||
using StandardScene.Utils;
|
||||
|
||||
namespace StandardScene.Signal
|
||||
{
|
||||
/// <summary>
|
||||
/// 磁条交管进程:只针对 MagCar。同区名排队后,按「本线 + 冲突对向线」站点并集查占用,容量允许则发启动。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 配置 <c>Config/Signal/mag-control-areas.json</c>。
|
||||
/// 同「管控区名称」绑成一个路口排队;放行时合并本线与冲突对向线的管控站点列表统计当前占用。
|
||||
/// 不使用 pending 在途占额。不处理 Mag2Car。
|
||||
/// </remarks>
|
||||
[MissionType(Name = "磁条交管进程", editor = typeof(MagTrafficMission))]
|
||||
[I18N.DocumentTranslation(Name = "Magnetic Traffic Mission", locale = "en")]
|
||||
public class MagTrafficMission : Mission
|
||||
{
|
||||
/// <summary>扫车周期(毫秒)。停在触发点的 MagCar 每拍排队判定一次。</summary>
|
||||
[FieldMember] public int TickMs = 1000;
|
||||
|
||||
/// <summary>管控区表路径。相对路径只解析工作目录 <c>Config/Signal</c>。</summary>
|
||||
[FieldMember] public string AreasPath = @"Config\Signal\mag-control-areas.json";
|
||||
|
||||
/// <summary>放行日志根目录。实际按车名落在其下 mag-traffic/car{name}/release_yyyyMMdd.log。</summary>
|
||||
[FieldMember] public string LogDirectory = "log";
|
||||
|
||||
/// <summary>是否把交管放行写入本地文件留档。</summary>
|
||||
[FieldMember] public bool EnableFileLog = true;
|
||||
|
||||
[JsonIgnore] private bool _started;
|
||||
[JsonIgnore] private readonly MagControlRuntime _runtime = new MagControlRuntime();
|
||||
[JsonIgnore] private CancellationTokenSource _cts;
|
||||
[JsonIgnore] private Thread _thread;
|
||||
|
||||
public class MagTrafficMissionStatus : MissionStatus
|
||||
{
|
||||
public int RuleCount { get; set; }
|
||||
public int WaitingAtTrigger { get; set; }
|
||||
public int PendingInFlight { get; set; }
|
||||
public int ScanTickCount { get; set; }
|
||||
public string AreasFile { get; set; }
|
||||
}
|
||||
|
||||
public override MissionStatus status { get; set; } = new MagTrafficMissionStatus();
|
||||
|
||||
public static Mission Create() => new MagTrafficMission();
|
||||
|
||||
[MethodMember(Name = "启动进程", Description = "加载管控区表,按区名排队后对 MagCar 发放行")]
|
||||
public override void Execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog);
|
||||
ReloadConfig();
|
||||
_started = true;
|
||||
StartWatch();
|
||||
MagTrafficFileLogger.WriteSystem($"进程启动 规则={((MagTrafficMissionStatus)status).RuleCount} 配置={((MagTrafficMissionStatus)status).AreasFile}");
|
||||
Diagnosis.Post(
|
||||
$"磁条交管进程已启动,规则={((MagTrafficMissionStatus)status).RuleCount}(仅 MagCar),放行日志={MagTrafficFileLogger.GetLogDirectory()}",
|
||||
"MagTraffic", true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
status.status = "启动失败";
|
||||
Diagnosis.Post($"磁条交管进程启动失败:{ExceptionFormatter.FormatEx(ex)}", "MagTraffic", true);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodMember(Name = "重新加载配置", Description = "重新读取 mag-control-areas.json")]
|
||||
public void ReloadConfig()
|
||||
{
|
||||
var file = SignalConfigStore.Resolve(AreasPath);
|
||||
var rows = SignalConfigStore.Load<MagControlAreaModel>(file);
|
||||
_runtime.Replace(rows);
|
||||
|
||||
var st = (MagTrafficMissionStatus)status;
|
||||
st.AreasFile = file;
|
||||
st.RuleCount = _runtime.RuleCount;
|
||||
st.PendingInFlight = _runtime.PendingCount;
|
||||
status.status = _started ? "运行中" : "配置已加载";
|
||||
MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog);
|
||||
MagTrafficFileLogger.WriteSystem($"重新加载配置 规则={st.RuleCount} 文件={file}");
|
||||
Diagnosis.Post($"磁条交管配置已加载:启用规则 {st.RuleCount} @ {file}", "MagTraffic", true);
|
||||
}
|
||||
|
||||
[MethodMember(Name = "停止进程")]
|
||||
public new void Stop()
|
||||
{
|
||||
_started = false;
|
||||
StopWatch();
|
||||
status.status = "已停止";
|
||||
MagTrafficFileLogger.WriteSystem("进程停止");
|
||||
Diagnosis.Post("磁条交管进程已停止", "MagTraffic", true);
|
||||
}
|
||||
|
||||
[MethodMember(Name = "打开放行日志目录", Description = "打开 mag-traffic 目录(按 car{name} 分子目录),便于按车查阅放行记录")]
|
||||
public void OpenReleaseLogFolder()
|
||||
{
|
||||
try
|
||||
{
|
||||
MagTrafficFileLogger.Configure(LogDirectory, EnableFileLog);
|
||||
var dir = MagTrafficFileLogger.GetLogDirectory();
|
||||
Directory.CreateDirectory(dir);
|
||||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = dir,
|
||||
UseShellExecute = true
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CycleUiHelper.Alert("错误", $"打开放行日志目录失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[MethodMember(Name = "打开管控区列表", Description = "编辑区名 / 兼容组 / 优先级 / 等待时长 / 触发点 / 区内站点 / 容量")]
|
||||
public void OpenAreas()
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = SignalConfigStore.Resolve(AreasPath);
|
||||
ModelListPanel<MagControlAreaModel>.Open(
|
||||
"磁条管控区配置",
|
||||
path,
|
||||
x => x == null ? "" : x.TriggerSit.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CycleUiHelper.Alert("错误", $"打开管控区列表失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void StartWatch()
|
||||
{
|
||||
StopWatch();
|
||||
_cts = new CancellationTokenSource();
|
||||
_thread = new Thread(WatchLoop)
|
||||
{
|
||||
IsBackground = true,
|
||||
Name = "MagTrafficWatch"
|
||||
};
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private void StopWatch()
|
||||
{
|
||||
try { _cts?.Cancel(); }
|
||||
catch { }
|
||||
try { _thread?.Join(2000); }
|
||||
catch { }
|
||||
_thread = null;
|
||||
}
|
||||
|
||||
private void WatchLoop()
|
||||
{
|
||||
var token = _cts.Token;
|
||||
var tick = 0;
|
||||
var interval = Math.Max(200, TickMs);
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (waiting, _) = _runtime.ScanAndRelease();
|
||||
var st = (MagTrafficMissionStatus)status;
|
||||
st.WaitingAtTrigger = waiting;
|
||||
st.PendingInFlight = _runtime.PendingCount;
|
||||
st.RuleCount = _runtime.RuleCount;
|
||||
st.ScanTickCount = ++tick;
|
||||
if (_started)
|
||||
status.status = $"运行中 规则{st.RuleCount} 等待{waiting}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Diagnosis.Log($"磁条交管扫车异常:{ex.Message}", "MagTraffic", true);
|
||||
}
|
||||
|
||||
try { Thread.Sleep(interval); }
|
||||
catch (ThreadInterruptedException) { break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user