fix: FASS2 状态机与 UDP 枢纽审查项

等锁超时、全路径签名、无锁窗口不下发、Fault 终态可等待、Pass+机构不再短路、Alarm 不杀单、catch-up 停在未完成站;VehicleCode=0/重复车号拒绝注册,Hub 已运行时不抢监听口;FileLogger 空目录可写。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
黄兆尉
2026-08-26 23:04:58 +08:00
co-authored by Cursor
parent 29a06f004f
commit e4a245e644
13 changed files with 465 additions and 48 deletions
+38 -3
View File
@@ -44,6 +44,7 @@ namespace StandardScene.CarTypes
private DateTime _lastPollTime = DateTime.MinValue;
private DateTime _lastUdpReportTime = DateTime.MinValue;
private bool _udpRegistered;
private bool _udpZeroCodeWarned;
private ushort _registeredVehicleCode = ushort.MaxValue;
private long _nextTaskId = 1;
private long _nextActionId = 1;
@@ -71,6 +72,7 @@ namespace StandardScene.CarTypes
[FieldMember] public bool VerifyTrajectoryFieldsOnStation = false;
[FieldMember] public int TaskResendIntervalMs = 500;
[FieldMember] public int ActionRetryIntervalMs = 1000;
[FieldMember] public int TrafficWaitTimeoutMs = 180000;
[FieldMember] public bool EnableTaskStateMachine = true;
[FieldMember] public bool EnableLoopTaskDrive = true;
[FieldMember] public bool StartBeforeMove = true;
@@ -567,6 +569,7 @@ namespace StandardScene.CarTypes
_taskStateMachine.LockCount = LockCount;
_taskStateMachine.ResendIntervalMs = TaskResendIntervalMs;
_taskStateMachine.ActionRetryIntervalMs = ActionRetryIntervalMs;
_taskStateMachine.TrafficWaitTimeoutMs = TrafficWaitTimeoutMs;
_taskStateMachine.StartBeforeMove = StartBeforeMove;
Fass2ActionResolver.VerifyTrajectoryFields = VerifyTrajectoryFieldsOnStation;
_taskStateMachine.Begin(startSiteId, goalSiteId, defaultSpeed);
@@ -1147,6 +1150,21 @@ namespace StandardScene.CarTypes
throw new InvalidOperationException("Mag2Car address is empty for UDP mode");
}
if (VehicleCode == 0)
{
if (!_udpZeroCodeWarned)
{
_udpZeroCodeWarned = true;
Diagnosis.Post(
$"Mag2Car {name}({id}) VehicleCode=0UDP 未注册。请为每台车配置唯一车号",
"Mag2Car",
true);
DetailLog("UDP register skipped: VehicleCode=0");
}
return;
}
if (!_udpRegistered || _registeredVehicleCode != VehicleCode)
{
if (_udpRegistered && _registeredVehicleCode != VehicleCode)
@@ -1155,11 +1173,28 @@ namespace StandardScene.CarTypes
_udpRegistered = false;
}
Fass2UdpHub.Register(this);
Fass2UdpHub.EnsureStarted(ListenPort);
if (!Fass2UdpHub.Register(this))
{
DetailLog($"UDP register rejected, VehicleCode={VehicleCode}");
return;
}
if (!Fass2UdpHub.IsRunning)
{
Fass2UdpHub.EnsureStarted(ListenPort);
}
else if (ListenPort > 0 && ListenPort != Fass2UdpHub.ListenPort)
{
var msg =
$"Mag2Car {name}({id}) ListenPort={ListenPort} 与已运行 Hub={Fass2UdpHub.ListenPort} 不一致,已忽略本车端口(配置错误)";
Diagnosis.Post(msg, "Mag2Car", true);
DetailLog(
$"UDP listen keep hub={Fass2UdpHub.ListenPort}, car ListenPort={ListenPort} ignored");
}
_udpRegistered = true;
_registeredVehicleCode = VehicleCode;
DetailLog($"UDP registered, VehicleCode={VehicleCode}, listen={ListenPort}, remote={address}:{Port}");
DetailLog($"UDP registered, VehicleCode={VehicleCode}, listen={Fass2UdpHub.ListenPort}, remote={address}:{Port}");
}
}