OPTHO FORMATING improve (ASIC,genesis)

Enhance iPerlHat protocol logging and error handling: add optical HEX formatting, improve diagnostic messages, and extend test command descriptions.
This commit is contained in:
Michal Buzik 2026-08-17 10:25:35 +02:00
parent 3488939995
commit 39941842d4
3 changed files with 131 additions and 18 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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<ReadingUnits>(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<FlipMode>(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;
}
}
}