diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index baae64d64..7aaf8e427 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("3.9.3137.0")] -[assembly: AssemblyFileVersion("3.9.3137.0")] +[assembly: AssemblyVersion("3.9.3138.0")] +[assembly: AssemblyFileVersion("3.9.3138.0")] diff --git a/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs b/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs index c93461bb1..dbec27810 100644 --- a/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs +++ b/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs @@ -2143,6 +2143,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations var encoding = optoSerialPort?.Encoding ?? Encoding.ASCII; byte[] bytes = encoding.GetBytes(line); log.Debug("ComPort: " + OptoComPortNr + " OPTHO RX ← " + HexFormatter.ToSerialHex(bytes)); + log.Debug("ComPort: " + OptoComPortNr + " OPTHO ASCII ← " + line.Replace('\t', ' ')); var streamingDecode = new StreamingDecoder(true); streamingDecode.DecodeMsg(line); diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index dc1a79e6b..105a4a7e5 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -1062,6 +1062,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead byte[] bytes = optoSerialPort.Encoding.GetBytes(line); log.Debug("ComPort: " + OptoComPortNr + " OPTHO RX ← " + HexFormatter.ToSerialHex(bytes)); + log.Debug("ComPort: " + OptoComPortNr + " OPTHO ASCII ← " + line.Replace('\t', ' ')); if (optoState == DataStreamState.ProcessAndSave) { diff --git a/TBFTests/Rig/RegisterReaders/iPerlASICReader/communication/C4/IperlHatProtocol/IperlHatIntegrationTests.cs b/TBFTests/Rig/RegisterReaders/iPerlASICReader/communication/C4/IperlHatProtocol/IperlHatIntegrationTests.cs index bda845ba5..cb1df9cc9 100644 --- a/TBFTests/Rig/RegisterReaders/iPerlASICReader/communication/C4/IperlHatProtocol/IperlHatIntegrationTests.cs +++ b/TBFTests/Rig/RegisterReaders/iPerlASICReader/communication/C4/IperlHatProtocol/IperlHatIntegrationTests.cs @@ -485,7 +485,11 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat string line = port.ReadLine(); // string byte[] bytes = port.Encoding.GetBytes(line); - Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(bytes)); + // Original byte-level output. Keep it for diagnostics. + Console.WriteLine( "RX ASCII bytes ← " + HexFormatter.ToSerialHex(bytes)); + // Customer-compatible optical HEX packet. + string opticalHex = FormatOpticalHexPacket(line); + Console.WriteLine( "OPTO HEX ← " + opticalHex); try { @@ -532,18 +536,24 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat TestViewCalibration(port); } } - + private static IperlHatResponse SendRequest( SerialPort port, byte[] request, - string commandName) + string commandName, + string commandDescription) { var parser = new IperlHatFrameParser(); - port.DiscardInBuffer(); - Console.WriteLine( $"{commandName} TX → " + HexFormatter.ToSerialHexWithAscii(request)); + Console.WriteLine(); + Console.WriteLine("=================================================="); + Console.WriteLine($"Command : {commandName}"); + Console.WriteLine($"Description : {commandDescription}"); + Console.WriteLine($"TX packet : {HexFormatter.ToSerialHexWithAscii(request)}"); + + port.DiscardInBuffer(); port.Write(request, 0, request.Length); - + byte[] response; try @@ -552,30 +562,74 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat } catch (TimeoutException ex) { - Assert.Fail( $"{commandName}: Timeout while waiting for response. " + ex.Message); + Assert.Fail($"{commandName}: Timeout while waiting for response." + + Environment.NewLine + + $"Description: {commandDescription}" + + Environment.NewLine + + $"TX packet: {HexFormatter.ToSerialHexWithAscii(request)}" + + Environment.NewLine + + $"Error: {ex.Message}"); + return null; } - Assert.IsNotNull( response, $"{commandName}: Response is null."); - Assert.IsTrue( response.Length > 0, $"{commandName}: Response is empty."); + Assert.IsNotNull(response, + $"{commandName}: Response is null. TX packet: {HexFormatter.ToSerialHexWithAscii(request)}"); - Console.WriteLine( $"{commandName} RX ← " + HexFormatter.ToSerialHexWithAscii(response)); + Assert.IsTrue(response.Length > 0, + $"{commandName}: Response is empty. TX packet: {HexFormatter.ToSerialHexWithAscii(request)}"); + + Console.WriteLine($"RX packet : {HexFormatter.ToSerialHexWithAscii(response)}"); try { IperlHatResponse decoded = parser.Parse(response); - Assert.IsNotNull( decoded, $"{commandName}: Parser returned null."); - Assert.IsTrue( decoded.IsOk, $"{commandName}: Device returned NOK. " + $"Payload={BitConverter.ToString(decoded.Payload ?? new byte[0])}"); + Assert.IsNotNull( + decoded, + $"{commandName}: Parser returned null." + + Environment.NewLine + + $"TX packet: {HexFormatter.ToSerialHexWithAscii(request)}" + + Environment.NewLine + + $"RX packet: {HexFormatter.ToSerialHexWithAscii(response)}"); + + Assert.IsTrue( + decoded.IsOk, + $"{commandName}: Device returned NOK." + + Environment.NewLine + + $"TX packet: {HexFormatter.ToSerialHexWithAscii(request)}" + + Environment.NewLine + + $"RX packet: {HexFormatter.ToSerialHexWithAscii(response)}" + + Environment.NewLine + + $"Payload: {BitConverter.ToString(decoded.Payload ?? new byte[0])}"); + + Console.WriteLine($"Result : OK"); + Console.WriteLine($"Payload : {BitConverter.ToString(decoded.Payload ?? new byte[0])}"); + return decoded; } + catch (AssertFailedException) + { + // Zachová pôvodnú a podrobnejšiu Assert chybu. + throw; + } catch (Exception ex) { - Assert.Fail( $"{commandName}: Response frame could not be parsed. " + $"Frame={BitConverter.ToString(response)}. Error={ex}"); + Assert.Fail( + $"{commandName}: Response frame could not be parsed." + + Environment.NewLine + + $"Description: {commandDescription}" + + Environment.NewLine + + $"TX packet: {HexFormatter.ToSerialHexWithAscii(request)}" + + Environment.NewLine + + $"RX packet: {HexFormatter.ToSerialHexWithAscii(response)}" + + Environment.NewLine + + $"Error: {ex}"); + return null; } } - + private static void TestViewVersionAndType( SerialPort port) { @@ -587,7 +641,8 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat IperlHatResponse response = SendRequest( port, request, - nameof(ProtocolCommand.ViewVersionAndType)); + nameof(ProtocolCommand.ViewVersionAndType), + "Reads the TouchRead version, meter device type and meter firmware version."); Assert.IsNotNull( response.Payload, "ViewVersionAndType: Payload is null."); Assert.IsTrue( response.Payload.Length > 0, "ViewVersionAndType: Payload is empty."); @@ -613,7 +668,12 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat .AddCommand(ProtocolCommand.ViewReadingUnits) .BuildBytes(); - IperlHatResponse response = SendRequest( port, request, nameof(ProtocolCommand.ViewReadingUnits)); + IperlHatResponse response = SendRequest( + port, + request, + nameof(ProtocolCommand.ViewReadingUnits), + "Reads the measurement units currently configured in the meter."); + ReadingUnits units = response.GetResponse(out bool responseOk); Assert.IsTrue( responseOk, $"ViewReadingUnits: Invalid payload. Payload={BitConverter.ToString(response.Payload ?? new byte[0])}"); @@ -632,7 +692,8 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat IperlHatResponse response = SendRequest( port, request, - nameof(ProtocolDeviceSubCommand.ViewFlipMode)); + nameof(ProtocolDeviceSubCommand.ViewFlipMode), + "Reads the current display flip mode."); FlipMode flipMode = response.GetResponse(out bool responseOk); @@ -649,7 +710,11 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat .AddDeviceCommand(ProtocolDeviceSubCommand.ViewCalibration) .BuildBytes(); - IperlHatResponse response = SendRequest( port, request, nameof(ProtocolDeviceSubCommand.ViewCalibration)); + IperlHatResponse response = SendRequest( + port, + request, + nameof(ProtocolDeviceSubCommand.ViewCalibration), + "Reads the raw two-byte calibration factor used to calculate the calibration percentage."); ushort rawValue = response.GetUInt16LittleEndian(out bool responseOk); @@ -665,5 +730,51 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat Assert.IsTrue( rawValue > 0, "ViewCalibration: Calibration factor must be greater than zero."); Assert.IsTrue( percentage > 0.0, "ViewCalibration: Calculated percentage must be greater than zero."); } + + private static string FormatOpticalHexPacket(string asciiPacket) + { + if (string.IsNullOrWhiteSpace(asciiPacket)) + throw new FormatException("Optical packet is empty."); + + string[] fields = asciiPacket.Split( + new[] { ' ', '\t', '\r', '\n' }, + StringSplitOptions.RemoveEmptyEntries); + + for (int i = 0; i < fields.Length; i++) + { + string field = fields[i].Trim(); + + if (!IsHexadecimal(field)) + { + throw new FormatException( + $"Optical packet contains a non-HEX field at index {i}: '{field}'."); + } + + fields[i] = field.ToUpperInvariant(); + } + + return string.Join(" ", fields); + } + + private static bool IsHexadecimal(string value) + { + if (string.IsNullOrEmpty(value)) + return false; + + for (int i = 0; i < value.Length; i++) + { + char c = value[i]; + + bool isHexDigit = + (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f'); + + if (!isHexDigit) + return false; + } + + return true; + } } } \ No newline at end of file