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:
parent
3488939995
commit
39941842d4
@ -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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user