✨ feat(server): 添加服务启动自动初始化机器人功能
* 在 ControllerClientCompatOptions 中新增 AutoInitOptions 配置模型 * 创建 AutoInitRobotHostedService 实现启动时自动初始化链路 * 在 appsettings.json 的 ControllerClientCompat.AutoInit 节配置 RobotName 和 RobotIp * 启动时依次执行 SetUpRobot → SetActiveController → Connect → EnableRobot;配置缺失或连接失败不阻止服务启动 * 更新 README.md 和现场工作流文档
This commit is contained in:
@@ -12,6 +12,10 @@ public sealed class FanucJ519Client : IDisposable
|
||||
private readonly object _commandLock = new();
|
||||
private readonly object _responseLock = new();
|
||||
private readonly ILogger<FanucJ519Client>? _logger;
|
||||
/// <summary>
|
||||
/// 指示预装队列发出 LastData 结束帧后是否进入仅监控状态,而不是继续发送保姿命令。
|
||||
/// </summary>
|
||||
private readonly bool _endCommandStreamAfterQueueDrained;
|
||||
private UdpClient? _udpClient;
|
||||
private CancellationTokenSource? _cts;
|
||||
private Thread? _receiveThread;
|
||||
@@ -25,8 +29,14 @@ public sealed class FanucJ519Client : IDisposable
|
||||
private long _slowSendCount;
|
||||
private long _maxReceiveToSendTicks;
|
||||
private uint _sequenceBufferSize;
|
||||
// 标记 StartMotion 前是否刚装载过新目标,用于区分新命令和上次运动残留目标。
|
||||
/// <summary>
|
||||
/// 在 StartMotion 前是否有待发送的新命令;如果为 true 则 StartMotion 不会清空当前目标,而是继续发送新目标。
|
||||
/// </summary>
|
||||
private bool _hasPendingCommandForStart;
|
||||
/// <summary>
|
||||
/// 标记命令流已通过 LastData 正常结束;该状态下仅接收状态包,不继续回发 hold 命令。
|
||||
/// </summary>
|
||||
private bool _monitorOnlyAfterLastData;
|
||||
private bool _motionStarted;
|
||||
private bool _disposed;
|
||||
|
||||
@@ -35,13 +45,22 @@ public sealed class FanucJ519Client : IDisposable
|
||||
/// </summary>
|
||||
public bool IsConnected => _udpClient is not null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取正常队列结束时是否通过 LastData 结束命令流并保留状态监控。
|
||||
/// </summary>
|
||||
internal bool EndCommandStreamAfterQueueDrained => _endCommandStreamAfterQueueDrained;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 FANUC J519 客户端。
|
||||
/// </summary>
|
||||
/// <param name="logger">日志记录器;允许 null,供无日志场景使用。</param>
|
||||
public FanucJ519Client(ILogger<FanucJ519Client>? logger = null)
|
||||
/// <param name="endCommandStreamAfterQueueDrained">队列结束帧发出后是否停止命令流并保留状态监控。</param>
|
||||
public FanucJ519Client(
|
||||
ILogger<FanucJ519Client>? logger = null,
|
||||
bool endCommandStreamAfterQueueDrained = true)
|
||||
{
|
||||
_logger = logger;
|
||||
_endCommandStreamAfterQueueDrained = endCommandStreamAfterQueueDrained;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -113,6 +132,7 @@ public sealed class FanucJ519Client : IDisposable
|
||||
}
|
||||
|
||||
_hasPendingCommandForStart = false;
|
||||
_monitorOnlyAfterLastData = false;
|
||||
_motionStarted = true;
|
||||
|
||||
}
|
||||
@@ -156,6 +176,7 @@ public sealed class FanucJ519Client : IDisposable
|
||||
{
|
||||
_motionStarted = false;
|
||||
_hasPendingCommandForStart = false;
|
||||
_monitorOnlyAfterLastData = false;
|
||||
CompleteCommandQueueLocked();
|
||||
}
|
||||
|
||||
@@ -178,6 +199,7 @@ public sealed class FanucJ519Client : IDisposable
|
||||
CompleteCommandQueueLocked();
|
||||
_currentCommand = command;
|
||||
_hasPendingCommandForStart = true;
|
||||
_monitorOnlyAfterLastData = false;
|
||||
_commandHistoryForTests?.Add(command);
|
||||
}
|
||||
|
||||
@@ -211,6 +233,8 @@ public sealed class FanucJ519Client : IDisposable
|
||||
// 队列耗尽后继续保持最后一帧目标,避免运动结束后回落到旧目标或空目标。
|
||||
_currentCommand = commands[^1];
|
||||
_hasPendingCommandForStart = true;
|
||||
_monitorOnlyAfterLastData = false;
|
||||
_motionStarted = true;
|
||||
_commandQueueDrainedCompletion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
_commandHistoryForTests?.AddRange(commands);
|
||||
}
|
||||
@@ -337,6 +361,7 @@ public sealed class FanucJ519Client : IDisposable
|
||||
CompleteCommandQueueLocked();
|
||||
_commandHistoryForTests = null;
|
||||
_hasPendingCommandForStart = false;
|
||||
_monitorOnlyAfterLastData = false;
|
||||
_motionStarted = false;
|
||||
}
|
||||
|
||||
@@ -375,6 +400,7 @@ public sealed class FanucJ519Client : IDisposable
|
||||
{
|
||||
CompleteCommandQueueLocked();
|
||||
_hasPendingCommandForStart = false;
|
||||
_monitorOnlyAfterLastData = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,9 +552,15 @@ public sealed class FanucJ519Client : IDisposable
|
||||
{
|
||||
FanucJ519Command? command;
|
||||
var willDrainQueue = false;
|
||||
var suppressHoldCommand = false;
|
||||
lock (_commandLock)
|
||||
{
|
||||
if (!_motionStarted)
|
||||
if (_monitorOnlyAfterLastData)
|
||||
{
|
||||
command = null;
|
||||
suppressHoldCommand = true;
|
||||
}
|
||||
else if (!_motionStarted)
|
||||
{
|
||||
command = null;
|
||||
}
|
||||
@@ -546,7 +578,7 @@ public sealed class FanucJ519Client : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
if (command is null)
|
||||
if (command is null && !suppressHoldCommand)
|
||||
{
|
||||
command = TryBuildHoldCommandFromLatestResponse(response);
|
||||
}
|
||||
@@ -574,7 +606,14 @@ public sealed class FanucJ519Client : IDisposable
|
||||
lock (_commandLock)
|
||||
{
|
||||
_lastSentCommand = command;
|
||||
if (willDrainQueue && _commandQueue is { Count: 0 })
|
||||
if (_endCommandStreamAfterQueueDrained && command.LastData == 1)
|
||||
{
|
||||
// LastData 是命令流的正常结束语义;结束后保留状态接收,但不继续回发保姿包。
|
||||
_monitorOnlyAfterLastData = true;
|
||||
_motionStarted = false;
|
||||
CompleteCommandQueueLocked();
|
||||
}
|
||||
else if (willDrainQueue && _commandQueue is { Count: 0 })
|
||||
{
|
||||
CompleteCommandQueueLocked();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user