IperlASIC - Improved and added tests, hardware integtration tests works
Improve `VersionTypeResult` parsing and handling: Add compact/legacy payload support. Extend `ReadingUnits`. Update `IperlHatIntegrationTests` and `RadioService` with new tests and functionality integration.
This commit is contained in:
parent
865528e344
commit
7a8ce7b6ab
@ -4,6 +4,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommon
|
||||
{
|
||||
CubicMeters = 0x00,
|
||||
CubicFeet = 0x01,
|
||||
UsGallons = 0x02
|
||||
UsGallons = 0x02,
|
||||
UsGallons1 = 0x04,
|
||||
UsGallons2 = 0x08,
|
||||
UsGallons3 = 0x10,
|
||||
}
|
||||
}
|
||||
@ -2,58 +2,134 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons
|
||||
{
|
||||
public class VersionTypeResult
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol
|
||||
{
|
||||
public string TouchReadVersion { get; set; }
|
||||
public string MeterDeviceType { get; set; }
|
||||
public string MeterFirmwareVersion { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
public class VersionTypeResult
|
||||
{
|
||||
return $"TouchReadVersion={TouchReadVersion}, " +
|
||||
$"MeterDeviceType={MeterDeviceType}, " +
|
||||
$"MeterFirmwareVersion={MeterFirmwareVersion}";
|
||||
}
|
||||
|
||||
|
||||
public static VersionTypeResult ParseVersionTypePayload(string payload)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(payload))
|
||||
return null;
|
||||
public string TouchReadVersion { get; set; }
|
||||
|
||||
// Example:
|
||||
// vers: Harry T:B800, V:06.06.01, FW:190215,
|
||||
// 7ECE, B1.6.01, HW:4, Serial:0
|
||||
public string MeterDeviceType { get; set; }
|
||||
|
||||
string meterDeviceType = GetPayloadValue(payload, "T");
|
||||
string touchReadVersion = GetPayloadValue(payload, "V");
|
||||
string meterFirmwareVersion = GetPayloadValue(payload, "FW");
|
||||
public string MeterFirmwareVersion { get; set; }
|
||||
|
||||
if (string.IsNullOrWhiteSpace(meterDeviceType) &&
|
||||
string.IsNullOrWhiteSpace(touchReadVersion) &&
|
||||
string.IsNullOrWhiteSpace(meterFirmwareVersion))
|
||||
public static VersionTypeResult ParseVersionTypePayload(
|
||||
string payload)
|
||||
{
|
||||
return null;
|
||||
if (string.IsNullOrWhiteSpace(payload))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string normalizedPayload = payload
|
||||
.Trim('\0', '\r', '\n', ' ');
|
||||
|
||||
VersionTypeResult result =
|
||||
ParseCompactPayload(normalizedPayload);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return ParseLegacyPayload(normalizedPayload);
|
||||
}
|
||||
|
||||
return new VersionTypeResult
|
||||
private static VersionTypeResult ParseCompactPayload(
|
||||
string payload)
|
||||
{
|
||||
MeterDeviceType = meterDeviceType,
|
||||
TouchReadVersion = touchReadVersion,
|
||||
MeterFirmwareVersion = meterFirmwareVersion
|
||||
};
|
||||
}
|
||||
// Expected format:
|
||||
// B1.23,SWM004,1.00
|
||||
|
||||
private static string GetPayloadValue(string payload, string key)
|
||||
{
|
||||
Match match = Regex.Match(
|
||||
payload,
|
||||
@"(?:^|[\s,])" + Regex.Escape(key) + @":\s*([^,\s]+)",
|
||||
RegexOptions.IgnoreCase);
|
||||
string[] parts = payload.Split(',');
|
||||
|
||||
return match.Success
|
||||
? match.Groups[1].Value.Trim()
|
||||
: null;
|
||||
if (parts.Length != 3)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string touchReadVersion = parts[0].Trim();
|
||||
string meterDeviceType = parts[1].Trim();
|
||||
string meterFirmwareVersion = parts[2].Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(touchReadVersion) ||
|
||||
string.IsNullOrWhiteSpace(meterDeviceType) ||
|
||||
string.IsNullOrWhiteSpace(meterFirmwareVersion))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new VersionTypeResult
|
||||
{
|
||||
TouchReadVersion = touchReadVersion,
|
||||
MeterDeviceType = meterDeviceType,
|
||||
MeterFirmwareVersion = meterFirmwareVersion
|
||||
};
|
||||
}
|
||||
|
||||
private static VersionTypeResult ParseLegacyPayload(
|
||||
string payload)
|
||||
{
|
||||
// Expected example:
|
||||
//
|
||||
// vers: Harry T:B800, V:06.06.01, FW:190215,
|
||||
// 7ECE, B1.6.01, HW:4, Serial:0
|
||||
|
||||
Match deviceTypeMatch = Regex.Match(
|
||||
payload,
|
||||
@"(?:^|[\s,])T\s*:\s*([^,\s]+)",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
Match versionMatch = Regex.Match(
|
||||
payload,
|
||||
@"(?:^|[\s,])V\s*:\s*([^,\s]+)",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
Match firmwareMatch = Regex.Match(
|
||||
payload,
|
||||
@"(?:^|[\s,])FW\s*:\s*([^,\s]+)",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
if (!deviceTypeMatch.Success ||
|
||||
!versionMatch.Success ||
|
||||
!firmwareMatch.Success)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string meterDeviceType =
|
||||
deviceTypeMatch.Groups[1].Value.Trim();
|
||||
|
||||
string touchReadVersion =
|
||||
versionMatch.Groups[1].Value.Trim();
|
||||
|
||||
string meterFirmwareVersion =
|
||||
firmwareMatch.Groups[1].Value.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(touchReadVersion) ||
|
||||
string.IsNullOrWhiteSpace(meterDeviceType) ||
|
||||
string.IsNullOrWhiteSpace(meterFirmwareVersion))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new VersionTypeResult
|
||||
{
|
||||
TouchReadVersion = touchReadVersion,
|
||||
MeterDeviceType = meterDeviceType,
|
||||
MeterFirmwareVersion = meterFirmwareVersion
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"TouchReadVersion={TouchReadVersion}, " +
|
||||
$"MeterDeviceType={MeterDeviceType}, " +
|
||||
$"MeterFirmwareVersion={MeterFirmwareVersion}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ using log4net;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons.TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.wiredProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.Utils;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
|
||||
|
||||
@ -9,6 +9,7 @@ using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.pars
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons.TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
|
||||
|
||||
|
||||
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
|
||||
@ -16,7 +17,8 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat
|
||||
[TestClass]
|
||||
public class IperlHatIntegrationTests
|
||||
{
|
||||
private const string ComPort = "COM3"; // CHANGE THIS
|
||||
private const string ComPort = "COM12"; // CHANGE THIS
|
||||
private const string ComPortOptho = "COM13";
|
||||
private const int BaudRate = 2400;
|
||||
private const int BaudRateOpto = 38400;
|
||||
private const int ReadTimeoutMs = 2000;
|
||||
@ -461,7 +463,7 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat
|
||||
//method test connection to optho head
|
||||
private void Serial_OptoRawSniff()
|
||||
{
|
||||
using (var port = new SerialPort("COM4", BaudRateOpto, Parity.None, 8, StopBits.One))
|
||||
using (var port = new SerialPort(ComPortOptho, BaudRateOpto, Parity.None, 8, StopBits.One))
|
||||
{
|
||||
port.Handshake = Handshake.None;
|
||||
port.ReadTimeout = 10000;
|
||||
@ -506,5 +508,163 @@ namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHat
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- NEXT COMMUNICATION ----
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Hardware")]
|
||||
[TestCategory("Serial")]
|
||||
public void Serial_ViewConfigurationCommands_ReturnValidResponses()
|
||||
{
|
||||
using (var port = new SerialPort(
|
||||
ComPort,
|
||||
BaudRate,
|
||||
Parity.None,
|
||||
8,
|
||||
StopBits.One))
|
||||
{
|
||||
port.Handshake = Handshake.None;
|
||||
port.ReadTimeout = 5000;
|
||||
port.Open();
|
||||
|
||||
TestViewVersionAndType(port);
|
||||
TestViewReadingUnits(port);
|
||||
TestViewFlipMode(port);
|
||||
TestViewCalibration(port);
|
||||
}
|
||||
}
|
||||
|
||||
private static IperlHatResponse SendRequest(
|
||||
SerialPort port,
|
||||
byte[] request,
|
||||
string commandName)
|
||||
{
|
||||
var parser = new IperlHatFrameParser();
|
||||
port.DiscardInBuffer();
|
||||
|
||||
Console.WriteLine( $"{commandName} TX → " + HexFormatter.ToSerialHexWithAscii(request));
|
||||
port.Write(request, 0, request.Length);
|
||||
|
||||
byte[] response;
|
||||
|
||||
try
|
||||
{
|
||||
response = ReadResponse(port);
|
||||
}
|
||||
catch (TimeoutException ex)
|
||||
{
|
||||
Assert.Fail( $"{commandName}: Timeout while waiting for response. " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
|
||||
Assert.IsNotNull( response, $"{commandName}: Response is null.");
|
||||
Assert.IsTrue( response.Length > 0, $"{commandName}: Response is empty.");
|
||||
|
||||
Console.WriteLine( $"{commandName} RX ← " + 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])}");
|
||||
return decoded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert.Fail( $"{commandName}: Response frame could not be parsed. " + $"Frame={BitConverter.ToString(response)}. Error={ex}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void TestViewVersionAndType(
|
||||
SerialPort port)
|
||||
{
|
||||
byte[] request = new IperlHatFrameBuilder()
|
||||
.RequestResponse(true)
|
||||
.AddCommand(ProtocolCommand.ViewVersionAndType)
|
||||
.BuildBytes();
|
||||
|
||||
IperlHatResponse response = SendRequest(
|
||||
port,
|
||||
request,
|
||||
nameof(ProtocolCommand.ViewVersionAndType));
|
||||
|
||||
Assert.IsNotNull( response.Payload, "ViewVersionAndType: Payload is null.");
|
||||
Assert.IsTrue( response.Payload.Length > 0, "ViewVersionAndType: Payload is empty.");
|
||||
|
||||
string payloadText = Encoding.ASCII.GetString(response.Payload).Trim('\0', '\r', '\n', ' ');
|
||||
|
||||
Console.WriteLine( "ViewVersionAndType payload: " + payloadText);
|
||||
|
||||
VersionTypeResult result = VersionTypeResult.ParseVersionTypePayload(payloadText);
|
||||
|
||||
Assert.IsNotNull( result, "ViewVersionAndType: Payload cannot be parsed. " + $"Payload='{payloadText}'");
|
||||
Assert.IsFalse( string.IsNullOrWhiteSpace(result.TouchReadVersion), "ViewVersionAndType: TouchReadVersion is empty.");
|
||||
Assert.IsFalse( string.IsNullOrWhiteSpace(result.MeterDeviceType), "ViewVersionAndType: MeterDeviceType is empty.");
|
||||
Assert.IsFalse( string.IsNullOrWhiteSpace(result.MeterFirmwareVersion), "ViewVersionAndType: MeterFirmwareVersion is empty.");
|
||||
|
||||
Console.WriteLine( "ViewVersionAndType result: " + result);
|
||||
}
|
||||
|
||||
private static void TestViewReadingUnits(SerialPort port)
|
||||
{
|
||||
byte[] request = new IperlHatFrameBuilder()
|
||||
.RequestResponse(true)
|
||||
.AddCommand(ProtocolCommand.ViewReadingUnits)
|
||||
.BuildBytes();
|
||||
|
||||
IperlHatResponse response = SendRequest( port, request, nameof(ProtocolCommand.ViewReadingUnits));
|
||||
ReadingUnits units = response.GetResponse<ReadingUnits>(out bool responseOk);
|
||||
|
||||
Assert.IsTrue( responseOk, $"ViewReadingUnits: Invalid payload. Payload={BitConverter.ToString(response.Payload ?? new byte[0])}");
|
||||
|
||||
Assert.IsTrue( Enum.IsDefined(typeof(ReadingUnits), units), $"ViewReadingUnits: Unknown value 0x{Convert.ToByte(units):X2}.");
|
||||
Console.WriteLine( $"ViewReadingUnits result: {units} " + $"(0x{Convert.ToByte(units):X2})");
|
||||
}
|
||||
|
||||
private static void TestViewFlipMode(SerialPort port)
|
||||
{
|
||||
byte[] request = new IperlHatFrameBuilder()
|
||||
.RequestResponse(true)
|
||||
.AddDeviceCommand(ProtocolDeviceSubCommand.ViewFlipMode)
|
||||
.BuildBytes();
|
||||
|
||||
IperlHatResponse response = SendRequest(
|
||||
port,
|
||||
request,
|
||||
nameof(ProtocolDeviceSubCommand.ViewFlipMode));
|
||||
|
||||
FlipMode flipMode = response.GetResponse<FlipMode>(out bool responseOk);
|
||||
|
||||
Assert.IsTrue( responseOk, $"ViewFlipMode: Invalid payload. Payload={BitConverter.ToString(response.Payload ?? new byte[0])}");
|
||||
Assert.IsTrue( Enum.IsDefined(typeof(FlipMode), flipMode),$"ViewFlipMode: Unknown value 0x{Convert.ToByte(flipMode):X2}.");
|
||||
|
||||
Console.WriteLine( $"ViewFlipMode result: {flipMode} (0x{Convert.ToByte(flipMode):X2})");
|
||||
}
|
||||
|
||||
private static void TestViewCalibration(SerialPort port)
|
||||
{
|
||||
byte[] request = new IperlHatFrameBuilder()
|
||||
.RequestResponse(true)
|
||||
.AddDeviceCommand(ProtocolDeviceSubCommand.ViewCalibration)
|
||||
.BuildBytes();
|
||||
|
||||
IperlHatResponse response = SendRequest( port, request, nameof(ProtocolDeviceSubCommand.ViewCalibration));
|
||||
|
||||
ushort rawValue = response.GetUInt16LittleEndian(out bool responseOk);
|
||||
|
||||
Assert.IsTrue( responseOk, "ViewCalibration: Expected a two-byte little-endian payload. " +
|
||||
$"Payload={BitConverter.ToString(response.Payload ?? new byte[0])}");
|
||||
|
||||
double percentage = rawValue * 100.0 / 4096.0;
|
||||
double correctionPercentage = percentage - 100.0;
|
||||
|
||||
Console.WriteLine( $"ViewCalibration result: RawValue={rawValue}, Percentage={percentage:F4} %, " +
|
||||
$"Correction={correctionPercentage:+0.0000;-0.0000;0.0000} %");
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ using TBF.Rig.TestMethods.iPerlCommunication.communication;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons.TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.wiredProtocol;
|
||||
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
|
||||
|
||||
@ -47,23 +48,14 @@ namespace TBFTests.Rig.TestMethods.iPerlCommunication.communication
|
||||
IperlResponseFactory.CreateVersionResponse(responseText);
|
||||
|
||||
// Act
|
||||
VersionTypeResult result =
|
||||
service.SetViewVersionAndType(head);
|
||||
VersionTypeResult result = service.SetViewVersionAndType(head);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
|
||||
Assert.AreEqual(
|
||||
"B800",
|
||||
result.MeterDeviceType);
|
||||
|
||||
Assert.AreEqual(
|
||||
"06.06.01",
|
||||
result.TouchReadVersion);
|
||||
|
||||
Assert.AreEqual(
|
||||
"190215",
|
||||
result.MeterFirmwareVersion);
|
||||
Assert.AreEqual( "B800", result.MeterDeviceType);
|
||||
Assert.AreEqual( "06.06.01", result.TouchReadVersion);
|
||||
Assert.AreEqual( "190215", result.MeterFirmwareVersion);
|
||||
|
||||
Assert.AreEqual(1, serialDriver.SendAndWaitCallCount);
|
||||
Assert.AreEqual(5000, serialDriver.LastTimeout);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user