using Sick.SafetyScanners.DataProcessing; using Sick.SafetyScanners.DataStructures; using Sick.SafetyScanners.Helpers; namespace Sick.SafetyScanners.Cola2.Commands; /// /// Command to request the latest telegram (measurement data) from the sensor via TCP /// Variable index: 179 + channel_index (179 for channel 0, 180 for channel 1, etc.) /// public sealed class LatestTelegramVariableCommand : CommandBase { private readonly ushort _variableIndex; private readonly ParseData _dataParser; private UdpScanData? _scanData; /// /// Creates a new LatestTelegramVariableCommand /// /// Channel index (0-3), defaults to 0 public LatestTelegramVariableCommand(sbyte channelIndex = 0) : base(0x52, 0x49) // 'R' and 'I' in ASCII (Read by Index) { if (channelIndex < 0 || channelIndex > 3) { throw new ArgumentOutOfRangeException(nameof(channelIndex), "Channel index must be between 0 and 3"); } // Variable index: 179 + channel_index _variableIndex = (ushort)(179 + channelIndex); _dataParser = new ParseData(); } public ushort VariableIndex => _variableIndex; public override bool CanBeExecutedWithoutSessionId => true; /// /// Gets the parsed scan data after the command has been executed successfully /// public UdpScanData? ScanData => _scanData; protected override ReadOnlyMemory AddTelegramData() { var data = new byte[2]; var span = data.AsSpan(); // Variable index (2 bytes, little endian) ReadWriteHelper.WriteUint16LittleEndian(span, 0, _variableIndex); return data; } protected override bool ProcessReplyInternal(ReadOnlyMemory replyData, byte replyCommandType, byte replyCommandMode) { // Reply should be 'R' (0x52) and 'A' (0x41) for Acknowledge if ((replyCommandType == 0x52 && replyCommandMode == 0x41) || (replyCommandType == 'R' && replyCommandMode == 'A')) { try { // Parse the TCP sequence data // The replyData contains the measurement data payload var packetBuffer = new PacketBuffer(replyData.ToArray(), replyData.Length); _scanData = _dataParser.ParseTcpSequence(packetBuffer); return true; } catch (Exception) { // Parsing failed return false; } } return false; } }