Initial commit
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user