using System.Text; using Sick.Tim781s.Colab.Helpers; namespace Sick.Tim781s.Colab.Commands; /// /// Command to read a value from the scanner (sRN - Read by Name) /// public sealed class ReadCommand : CommandBase { public ReadCommand(string variableName) : base($"sRN {variableName}") { VariableName = variableName; } public string VariableName { get; } public string? ReplyValue { get; private set; } public byte[]? RawReplyData { get; private set; } public override bool ProcessReply(ReadOnlyMemory replyData) { // Store raw reply data for binary parsing RawReplyData = replyData.ToArray(); // Parse reply: "sAN " or "sRA " // For binary data, only the header is ASCII, the rest is binary // Try to find where ASCII header ends var asciiHeaderEnd = -1; for (int i = 0; i < replyData.Length && i < 100; i++) { if (replyData.Span[i] == 0 || replyData.Span[i] > 127) { // Found non-ASCII byte, header ends here asciiHeaderEnd = i; break; } } // If we found where ASCII ends, only decode that part var headerLength = asciiHeaderEnd > 0 ? asciiHeaderEnd : Math.Min(replyData.Length, 100); var replyString = Encoding.ASCII.GetString(replyData.Span.Slice(0, headerLength)); // Check if reply starts with "sAN" (Answer) or "sRA" (Read Answer) if (!replyString.StartsWith("sAN", StringComparison.Ordinal) && !replyString.StartsWith("sRA", StringComparison.Ordinal)) { WasSuccessful = false; return false; } // Extract value after variable name var parts = replyString.Split(' ', StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 2 && parts[1] == VariableName) { // For binary data, ReplyValue will contain ASCII header only // The actual binary data is in RawReplyData if (parts.Length >= 3) { ReplyValue = string.Join(" ", parts.Skip(2)); } else { // Binary data follows immediately after header ReplyValue = string.Empty; } WasSuccessful = true; return true; } WasSuccessful = false; return false; } }