120 lines
3.1 KiB
C#
120 lines
3.1 KiB
C#
using Sick.Tim781s.Colab.Commands;
|
|
using Sick.Tim781s.Colab.Helpers;
|
|
using Sick.Tim781s.Colab.Interfaces;
|
|
|
|
namespace Sick.Tim781s.Colab;
|
|
|
|
/// <summary>
|
|
/// ColaB session manager for handling send, receive and process telegrams
|
|
/// </summary>
|
|
public sealed class ColaBSession : IDisposable
|
|
{
|
|
private readonly ITcpClient _tcpClient;
|
|
private readonly object _lock = new();
|
|
private bool _disposed;
|
|
|
|
public bool IsOpen
|
|
{
|
|
get
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return _tcpClient.IsConnected;
|
|
}
|
|
}
|
|
}
|
|
|
|
public ColaBSession(ITcpClient tcpClient)
|
|
{
|
|
_tcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens the session (connects to scanner)
|
|
/// </summary>
|
|
public void Open(int timeoutMs = 5000)
|
|
{
|
|
if (_disposed)
|
|
throw new ObjectDisposedException(nameof(ColaBSession));
|
|
|
|
if (IsOpen)
|
|
return;
|
|
|
|
_tcpClient.Connect(timeoutMs);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Closes the session (disconnects from scanner)
|
|
/// </summary>
|
|
public void Close()
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
|
|
_tcpClient.Disconnect();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Executes a command and waits for reply
|
|
/// </summary>
|
|
public void ExecuteCommand(IColaBCommand command, int timeoutMs = 5000)
|
|
{
|
|
if (_disposed)
|
|
throw new ObjectDisposedException(nameof(ColaBSession));
|
|
|
|
if (!IsOpen)
|
|
throw new InvalidOperationException("Session is not open");
|
|
|
|
// Create ColaB frame from command
|
|
var commandData = command.GetCommandData();
|
|
var frame = ColaBHelper.CreateFrame(commandData.Span);
|
|
|
|
// Send frame
|
|
_tcpClient.Send(frame);
|
|
|
|
// Receive reply with retry logic
|
|
byte[]? replyFrame = null;
|
|
int retries = 3;
|
|
for (int i = 0; i < retries; i++)
|
|
{
|
|
try
|
|
{
|
|
replyFrame = _tcpClient.Receive(timeoutMs);
|
|
break;
|
|
}
|
|
catch (TimeoutException) when (i < retries - 1)
|
|
{
|
|
// Retry on timeout
|
|
System.Threading.Thread.Sleep(100);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (replyFrame == null || replyFrame.Length == 0)
|
|
{
|
|
throw new TimeoutException($"No reply received after {retries} attempts");
|
|
}
|
|
|
|
// Parse frame and extract command data
|
|
if (ColaBHelper.TryParseFrame(replyFrame, out var replyData, out _))
|
|
{
|
|
// Process reply
|
|
command.ProcessReply(replyData.ToArray());
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException($"Failed to parse reply frame. Raw reply: {BitConverter.ToString(replyFrame.Take(64).ToArray())}");
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
|
|
Close();
|
|
_disposed = true;
|
|
}
|
|
}
|
|
|