Add unit tests for iPerl communication protocols, including hex logger, LED parsers, wired protocols, and frame builders. Update project file to include new test suites.

This commit is contained in:
Michal Buzik 2026-02-15 22:45:37 +01:00
parent c30e8540b2
commit 6d959ddf96
11 changed files with 1563 additions and 0 deletions

View File

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AListViewItem_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F842e321b8a9b41deb8ae4f08b8882c8a5b8998_003Fc4_003F40fa24bf_003FListViewItem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:Boolean x:Key="/Default/Environment/UnitTesting/CreateUnitTestDialog/ShowAdvancedOptions/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/UnitTesting/CreateUnitTestDialog/ShowAdvancedOptions/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/Environment/UnitTesting/CreateUnitTestDialog/TestProjectMapping/=743DF7DB_002DC7B6_002D42EB_002D986D_002D0F485E5588E4/@EntryIndexedValue">77EB589F-C670-4489-AAD6-2A3C02061FD1</s:String> <s:String x:Key="/Default/Environment/UnitTesting/CreateUnitTestDialog/TestProjectMapping/=743DF7DB_002DC7B6_002D42EB_002D986D_002D0F485E5588E4/@EntryIndexedValue">77EB589F-C670-4489-AAD6-2A3C02061FD1</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/CreateUnitTestDialog/TestProjectMapping/=8648FD92_002DCDA1_002D4C3A_002DB5F9_002DFE547CE1FA48/@EntryIndexedValue">77EB589F-C670-4489-AAD6-2A3C02061FD1</s:String> <s:String x:Key="/Default/Environment/UnitTesting/CreateUnitTestDialog/TestProjectMapping/=8648FD92_002DCDA1_002D4C3A_002DB5F9_002DFE547CE1FA48/@EntryIndexedValue">77EB589F-C670-4489-AAD6-2A3C02061FD1</s:String>

View File

@ -0,0 +1,180 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
{
[TestClass]
public class IperlHatFrameBuilderTests
{
[TestMethod]
public void Encode_ViewFactoryId_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewFactoryId)
.BuildBytes();
byte[] expected =
{
IperlHatProtocolConstants.Start, // START
IperlHatProtocolConstants.Write, // DIRECTION
0x05, // LEN
(byte)ProtocolCommand.ViewFactoryId, // COMMAND
IperlHatProtocolConstants.End // END
};
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_VERS_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.Question)
.AddPayload(IperlHatProtocolConstants.Version)
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 3F 76 65 72 73 0D");
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_VERS2_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.SetVersionCommand()
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 3F 76 65 72 73 0D");
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_ViewProgrammableId_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewProgrammableId)
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 05 03 0D");
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_ViewState_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewState)
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 05 19 0D");
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_SetState_Idle_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Idle) // Idle
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 06 1A 01 0D");
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_SetState_Active_Command()
{
byte[] frame = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Active) // Active
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 06 1A 02 0D");
CollectionAssert.AreEqual(expected, frame);
string log = IperlHatLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_SetDiagnosticLEDState_Status4_Command()
{
// ----------- Arrange -----------
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
.AddPayload(DiagnosticLedState.State4)
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 07 FD 60 04 0D");
CollectionAssert.AreEqual(expected, request);
string log = IperlHatLogger.DescribeTx(request);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(request));
}
[TestMethod]
public void AddDiagnosticLedState()
{
// ----------- Arrange -----------
byte[] request = new IperlHatFrameBuilder()
.AddDiagnosticLedState(DiagnosticLedState.State4)
.BuildBytes();
byte[] expected = HexFormatter.HexStringToByteArray("53 57 07 FD 60 04 0D");
CollectionAssert.AreEqual(expected, request);
string log = IperlHatLogger.DescribeTx(request);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(request));
}
}
}

View File

@ -0,0 +1,116 @@
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
{
[TestClass]
[TestSubject(typeof(IperlHatFrameParser))]
public class IperlHatFrameParserTest
{
[TestMethod]
public void ParseTest_FactoryID()
{
IperlHatFrameParser parser = new IperlHatFrameParser();
byte[] result1 = HexFormatter.HexStringToByteArray("53 52 0F 01 31 30 30 31 30 34 30 35 31 00 0D");
IperlHatResponse iperlHatResponse = parser.Parse(result1);
Assert.IsNotNull(iperlHatResponse);
Assert.IsTrue(iperlHatResponse.IsOk);
Assert.IsTrue(iperlHatResponse.Payload.Length > 0);
Assert.AreEqual("100104051", iperlHatResponse.GetAsciiPayload());
}
[TestMethod]
public void ParseTest_VERS()
{
IperlHatFrameParser parser = new IperlHatFrameParser();
byte[] versionResult = HexFormatter.HexStringToByteArray("3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20 56 3A 30 36 2E 30 36 2E 30 31 2C 20 46 57 3A 31 39 30 32 31 35 2C 20 37 45 43 45 2C 20 42 31 2E 36 2E 30 31 2C 20 48 57 3A 34 2C 20 53 65 72 69 61 6C 3A 30 0D");
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsTrue(iperlHatResponse.IsOk);
Assert.IsTrue(iperlHatResponse.Payload.Length > 0);
Assert.AreEqual(IperlHatProtocolConstants.Question, iperlHatResponse.Control);
Assert.AreEqual("vers: Harry T:B800, V:06.06.01, FW:190215, 7ECE, B1.6.01, HW:4, Serial:0", iperlHatResponse.GetAsciiPayload());
}
[TestMethod]
public void ParseTest_Response_OK ()
{
IperlHatFrameParser parser = new IperlHatFrameParser();
byte[] versionResult = HexFormatter.HexStringToByteArray("53 52 05 01 0D");
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsTrue(iperlHatResponse.IsOk);
Assert.AreEqual(null, iperlHatResponse.GetAsciiPayload());
}
[TestMethod]
public void ParseTest_Response_NOK ()
{
IperlHatFrameParser parser = new IperlHatFrameParser();
byte[] versionResult = HexFormatter.HexStringToByteArray("53 52 05 FD 0D");
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsFalse(iperlHatResponse.IsOk);
Assert.AreEqual(null, iperlHatResponse.GetAsciiPayload());
}
[TestMethod]
public void ParseTest_Response_State ()
{
IperlHatFrameParser parser = new IperlHatFrameParser();
// IDLE
byte[] versionResult = HexFormatter.HexStringToByteArray("53 52 06 01 01 0D");
IperlHatResponse iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsFalse(iperlHatResponse.IsOk);
ProtocolStatuses status = iperlHatResponse.GetResponse<ProtocolStatuses>(out bool isOk);
Assert.AreEqual(true, isOk);
Assert.AreEqual(ProtocolStatuses.Idle, status);
//ACTIVE
versionResult = HexFormatter.HexStringToByteArray("53 52 06 01 02 0D");
iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsFalse(iperlHatResponse.IsOk);
status = iperlHatResponse.GetResponse<ProtocolStatuses>(out isOk);
Assert.AreEqual(true, isOk);
Assert.AreEqual(ProtocolStatuses.Active, status);
//EndOfLife
versionResult = HexFormatter.HexStringToByteArray("53 52 06 01 03 0D");
iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsFalse(iperlHatResponse.IsOk);
status = iperlHatResponse.GetResponse<ProtocolStatuses>(out isOk);
Assert.AreEqual(true, isOk);
Assert.AreEqual(ProtocolStatuses.EndOfLife, status);
//MeterTest
versionResult = HexFormatter.HexStringToByteArray("53 52 06 01 04 0D");
iperlHatResponse = parser.Parse(versionResult);
Assert.IsNotNull(iperlHatResponse);
Assert.IsFalse(iperlHatResponse.IsOk);
status = iperlHatResponse.GetResponse<ProtocolStatuses>(out isOk);
Assert.AreEqual(true, isOk);
Assert.AreEqual(ProtocolStatuses.MeterTest, status);
}
}
}

View File

@ -0,0 +1,510 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.IperlHatProtocol
{
[TestClass]
public class IperlHatIntegrationTests
{
private const string ComPort = "COM3"; // CHANGE THIS
private const int BaudRate = 2400;
private const int BaudRateOpto = 38400;
private const int ReadTimeoutMs = 2000;
[TestMethod]
[TestCategory("Hardware")]
[TestCategory("Serial")]
public void Serial_ViewFactoryId_ReadSerialNumber()
{
// -------- Arrange --------
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewFactoryId)
.BuildBytes();
var parser = new IperlHatFrameParser();
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
{
port.Handshake = Handshake.None;
port.ReadTimeout = 5000;
port.Open();
DateTime end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
port.Write(request, 0, request.Length);
Console.WriteLine("Listening for 10 seconds...");
byte[] response = null;
while (DateTime.Now < end)
{
try
{
response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
IperlHatResponse iperlHatResponse = parser.Parse(response);
Assert.IsTrue(iperlHatResponse.IsOk);
Assert.IsFalse(iperlHatResponse.Payload.Length < 8);
Console.WriteLine("\nDone.");
}
}
[TestMethod]
[TestCategory("Hardware")]
[TestCategory("Serial")]
public void Serial_SetStatus_Idle_Active()
{
byte[] requestStatus = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewState)
.BuildBytes();
var parser = new IperlHatFrameParser();
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
{
port.Handshake = Handshake.None;
port.ReadTimeout = 5000;
port.Open();
DateTime end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(requestStatus));
port.Write(requestStatus, 0, requestStatus.Length);
Console.WriteLine("Listening for 10 seconds...");
byte[] resStart = null;
while (DateTime.Now < end)
{
try
{
resStart = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(resStart));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
IperlHatResponse iperlHatResponseOld = parser.Parse(resStart);
Assert.IsTrue(iperlHatResponseOld.IsOk, "Idle No set!");
Console.WriteLine("We start with status: " + HexFormatter.ToHex(iperlHatResponseOld.Payload[0]));
//----------------------------------------------------------------
// -------- Arrange --------
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Idle)
.BuildBytes();
// -- set idle
end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
port.Write(request, 0, request.Length);
Console.WriteLine("Listening for 10 seconds...");
byte[] response = null;
while (DateTime.Now < end)
{
try
{
response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
IperlHatResponse iperlHatResponse = parser.Parse(response);
Assert.IsTrue(iperlHatResponse.IsOk, "Idle No set!");
//----------------------------------------------------------------
request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Active)
.BuildBytes();
end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
port.Write(request, 0, request.Length);
Console.WriteLine("Listening for 10 seconds...");
response = null;
while (DateTime.Now < end)
{
try
{
response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
iperlHatResponse = parser.Parse(response);
Assert.IsTrue(iperlHatResponse.IsOk, "Idle No set!");
//--------------------------------------------------------------------
Console.WriteLine("\nDone.");
}
}
[TestMethod]
[TestCategory("Hardware")]
public void Serial_RawSniff()
{
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
{
port.Handshake = Handshake.None;
port.ReadTimeout = 5000;
port.Open();
DateTime end = DateTime.Now.AddSeconds(10);
//welcome message
byte[] frame = HexFormatter.HexStringToByteArray("53 57 3F 76 65 72 73 0D");
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(frame));
port.Write(frame, 0, frame.Length);
Console.WriteLine("Listening for 10 seconds...");
while (DateTime.Now < end)
{
try
{
byte[] response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ",e);
}
}
end = DateTime.Now.AddSeconds(10);
byte[] frameID = HexFormatter.HexStringToByteArray("53 57 05 01 0D");
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(frameID));
port.Write(frameID, 0, frameID.Length);
Console.WriteLine("Listening for 10 seconds...");
while (DateTime.Now < end)
{
try
{
byte[] response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ",e);
}
}
Console.WriteLine("\nDone.");
}
}
public static byte[] ReadResponse(SerialPort port)
{
var result = new List<byte>();
try
{
while (true)
{
int value = port.ReadByte(); // blocks until byte or timeout
if (value < 0)
throw new IOException("Serial port returned end of stream.");
byte b = HexFormatter.ToHexByte(value);
result.Add(b);
// stop when CR received
if (b == 0x0D)
break;
}
return result.ToArray();
}
catch (TimeoutException ex)
{
if (result.Count > 0)
return result.ToArray();
throw new TimeoutException("Timeout reading response from serial port.", ex);
}
}
[TestMethod]
[TestCategory("Hardware")]
public void OptoCommunicationON_ReadOpto_CommunicatonOFF()
{
//OPEN COMMUNICATION to Iperl Hat
var parser = new IperlHatFrameParser();
using (var port = new SerialPort(ComPort, BaudRate, Parity.None, 8, StopBits.One))
{
port.Handshake = Handshake.None;
port.ReadTimeout = 5000;
port.Open();
//----------------------------------------------------------------
// ------ Set active mode ------
//----------------------------------------------------------------
byte[] requestStatus = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Active)
.BuildBytes();
DateTime end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(requestStatus));
port.Write(requestStatus, 0, requestStatus.Length);
Console.WriteLine("Set active mode - Listening for 10 seconds...");
byte[] resStart = null;
while (DateTime.Now < end)
{
try
{
resStart = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(resStart));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
IperlHatResponse iperlHatResponseOld = parser.Parse(resStart);
Assert.IsTrue(iperlHatResponseOld.IsOk, "Active No set!");
//----------------------------------------------------------------
// ------ Enable Opto data ------
//----------------------------------------------------------------
// ----------- Arrange -----------
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
.AddPayload(DiagnosticLedState.State4)
.BuildBytes();
end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
port.Write(request, 0, request.Length);
Console.WriteLine("Enable Opto data - Listening for 10 seconds...");
byte[] response = null;
while (DateTime.Now < end)
{
try
{
response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
IperlHatResponse iperlHatResponse = parser.Parse(response);
Assert.IsTrue(iperlHatResponse.IsOk, "Opto data not set!");
//----------------------------------------------------------------
// ------ Test Opto data ------
//----------------------------------------------------------------
//Now try test opto data
Serial_OptoRawSniff();
//----------------------------------------------------------------
// ------ Disable Opto data ------
//----------------------------------------------------------------
// ----------- Arrange -----------
request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
.AddPayload(DiagnosticLedState.StateOFF)
.BuildBytes();
end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
port.Write(request, 0, request.Length);
Console.WriteLine("Disable Opto data - Listening for 10 seconds...");
response = null;
while (DateTime.Now < end)
{
try
{
response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
iperlHatResponse = parser.Parse(response);
Assert.IsTrue(iperlHatResponse.IsOk, "Disabled opto LED not set!");
//----------------------------------------------------------------
// ------ Set Idle mode ------
//----------------------------------------------------------------
// ----------- Arrange -----------
request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Idle)
.BuildBytes();
end = DateTime.Now.AddSeconds(10);
Console.WriteLine("TX → " + HexFormatter.ToSerialHexWithAscii(request));
port.Write(request, 0, request.Length);
Console.WriteLine("Set Idle mode - Listening for 10 seconds...");
response = null;
while (DateTime.Now < end)
{
try
{
response = ReadResponse(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHexWithAscii(response));
break;
}
catch (TimeoutException e)
{
Assert.Fail("Timeout: ", e);
}
}
iperlHatResponse = parser.Parse(response);
Assert.IsTrue(iperlHatResponse.IsOk, "Idle status not set!");
//----------------------------------------------------------------
// ------ Test finished ------
//----------------------------------------------------------------
Console.WriteLine("\nDone.");
}
}
/// <summary>
/// This test work only if Opto data are active
/// Use OptoCommunicationON_ReadOpto_CommunicatonOFF() test method
/// </summary>
[TestMethod]
[TestCategory("Hardware")]
public void Serial_OptoRawSniff_Standalone()
{
Serial_OptoRawSniff();
}
//method test connection to optho head
private void Serial_OptoRawSniff()
{
using (var port = new SerialPort("COM4", BaudRateOpto, Parity.None, 8, StopBits.One))
{
port.Handshake = Handshake.None;
port.ReadTimeout = 10000;
// 🔑 CRLF handling
port.NewLine = "\r\n";
port.Encoding = Encoding.ASCII; // or UTF8 if needed
port.Open();
Console.WriteLine("Listening for 10 seconds...");
DateTime end = DateTime.Now.AddSeconds(10);
var parser = new DiagnosticLedParser(DiagnosticLedState.State4);
while (DateTime.Now < end)
{
try
{
string line = port.ReadLine(); // string
byte[] bytes = port.Encoding.GetBytes(line);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(bytes));
try
{
var data = (DiagnosticLedState4Data)parser.ParseLine(line,false);
Console.WriteLine("Parsed: " + data);
}catch(Exception e)
{
Console.WriteLine("Failed to parse: " + e.Message);
}
}
catch (TimeoutException)
{
Assert.Fail("Serial read timeout");
}
}
Console.WriteLine("\nDone.");
}
}
}
}

View File

@ -0,0 +1,190 @@
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.diagnosticLed
{
[TestClass]
[TestSubject(typeof(DiagnosticLedParser))]
public class DiagnosticLedParserTest
{
private static string WithChecksum(string bodyWithoutChecksum)
{
byte sum = 0;
foreach (char c in bodyWithoutChecksum)
sum += (byte)c;
return bodyWithoutChecksum + sum.ToString("X2") + "\r\n";
}
[TestMethod]
public void Parse_DiagnosticLed_State1()
{
string body =
"FFFF9C\t" + // signed 24-bit ADC = -100
"2020\t" + // field strength
"FFFA\t" + // raw flow (-6)
"0050FC\t" + // raw volume
"0054\t"; // capacitor mV
string line = WithChecksum(body);
var parser = new DiagnosticLedParser(DiagnosticLedState.State1);
var data = (DiagnosticLedState1Data)parser.ParseLine(line);
Assert.AreEqual(-100, data.Adc24);
Assert.AreEqual((ushort)0x2020, data.FieldStrength);
Assert.AreEqual((short)-6, data.RawFlow);
Assert.AreEqual((uint)0x0050FC, data.RawVolume);
Assert.AreEqual((ushort)0x0054, data.CapacitorMv);
}
[TestMethod]
public void Parse_DiagnosticLed_State2()
{
string line =
"00004F\t029A\t0000\tFFD3B1\t005C\t3B9AC9B1\t02\t01\t0D\r\n";
var parser = new DiagnosticLedParser(DiagnosticLedState.State2);
var data = (DiagnosticLedState2Data)parser.ParseLine(line);
Assert.AreEqual(79, data.Adc24);
Assert.AreEqual((ushort)666, data.FieldStrength);
Assert.AreEqual((short)0, data.RawFlow);
Assert.AreEqual(0xFFD3B1u, data.RawVolume);
Assert.AreEqual((ushort)92, data.CapacitorMv);
Assert.AreEqual(0x3B9AC9B1u, data.LcdVolume);
Assert.AreEqual((byte)0x02, data.MeterState);
Assert.IsTrue(data.IsLowFlowCutoff);
}
[TestMethod]
public void Parse_DiagnosticLed_State3()
{
string body =
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t";
string line = WithChecksum(body);
var parser = new DiagnosticLedParser(DiagnosticLedState.State3);
var data = (DiagnosticLedState3Data)parser.ParseLine(line);
Assert.AreEqual(-13303, data.Adc24);
Assert.AreEqual((ushort)0x2020, data.FieldStrength);
Assert.AreEqual((short)-6, data.RawFlow);
Assert.AreEqual((uint)0x0050FC, data.RawVolume);
Assert.AreEqual((ushort)0x0054, data.CapacitorMv);
Assert.AreEqual((ushort)0x0B01, data.FieldCalibration);
Assert.AreEqual((uint)0x048000, data.AsicTimestamp);
Assert.AreEqual((byte)0xA7, data.FieldDriveTimeUs);
}
[TestMethod]
public void Parse_DiagnosticLed_State4()
{
string body =
"000ABC\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
"00001234\t00F0\t00F1\t0100\t0200\t03\t";
string line = WithChecksum(body);
var parser = new DiagnosticLedParser(DiagnosticLedState.State4);
var data = (DiagnosticLedState4Data)parser.ParseLine(line);
Assert.AreEqual(2748, data.Adc24);
Assert.AreEqual((ushort)0x2020, data.FieldStrength);
Assert.AreEqual((short)-6, data.RawFlow);
Assert.AreEqual((uint)0x0050FC, data.RawVolume);
Assert.AreEqual((ushort)0x0054, data.CapacitorMv);
Assert.AreEqual((ushort)0x0B01, data.FieldCalibration);
Assert.AreEqual((uint)0x048000, data.AsicTimestamp);
Assert.AreEqual((byte)0xA7, data.FieldDriveTimeUs);
Assert.AreEqual(0x00001234, data.MeanFlowRate);
Assert.AreEqual((ushort)0x00F0, data.Field1Measurement);
Assert.AreEqual((ushort)0x00F1, data.Field2Measurement);
Assert.AreEqual((ushort)0x0100, data.IntegratorCalibrationPositive);
Assert.AreEqual((ushort)0x0200, data.IntegratorCalibrationNegative);
Assert.AreEqual((byte)0x03, data.AsicState);
}
[TestMethod]
public void Parse_DiagnosticLed_State5()
{
string body =
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
"00001234\t00F0\t00F1\t0100\t0200\t03\tFFEC\t";
string line = WithChecksum(body);
var parser = new DiagnosticLedParser(DiagnosticLedState.State5);
var data = (DiagnosticLedState5Data)parser.ParseLine(line);
Assert.AreEqual((short)-20, data.WaterImpedance);
Assert.AreEqual((byte)0x03, data.AsicState);
}
[TestMethod]
public void Parse_DiagnosticLed_State6()
{
string body =
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
"00001234\t00F0\t00F1\t0100\t0200\t03\tFFEC\t0010\t" +
"02\t" + // pp spike detection
"02\t" + // ll pipe status
"00000099\t" + // LCD volume
"01\t"; // ASIC state1
string line = WithChecksum(body);
var parser = new DiagnosticLedParser(DiagnosticLedState.State6);
var data = (DiagnosticLedState6Data)parser.ParseLine(line);
Assert.AreEqual((short)-20, data.WaterImpedance);
Assert.AreEqual((short)0x0010, data.ElectrodeDeltaMv);
Assert.AreEqual((byte)0x02, data.SpikeDetection);
Assert.AreEqual((byte)0x02, data.PipeStatus);
Assert.AreEqual((uint)0x99, data.LcdVolume);
Assert.AreEqual((byte)0x01, data.AsicState1);
}
[TestMethod]
public void Parse_DiagnosticLed_State7()
{
string body =
"FFCC09\t2020\tFFFA\t0050FC\t0054\t0B01\t048000\tA7\t" +
"00001234\t00F0\t00F1\t0100\t0200\t03\tFFEC\t0010\t" +
"02\t" + // pp spike detection
"02\t" + // ll pipe status
"00000099\t" + // LCD volume
"01\t" + // ASIC state1
"FFAA10\t" + // raw ADC before offset
"000123\t" + // detrended ADC
"FFEE\t" + // imaginary water impedance
"0011\t" + // electrode voltage noise
"03\t"; // ADC offset learning status
string line = WithChecksum(body);
var parser = new DiagnosticLedParser(DiagnosticLedState.State7);
var data = (DiagnosticLedState7Data)parser.ParseLine(line);
Assert.AreEqual(-22000, data.RawAdcBeforeOffset);
Assert.AreEqual(0x000123, data.DetrendedAdc);
Assert.AreEqual((short)-18, data.ImaginaryWaterImpedance);
Assert.AreEqual((ushort)0x0011, data.ElectrodeVoltageNoise);
Assert.AreEqual((byte)0x03, data.AdcOffsetLearningStatus);
}
}
}

View File

@ -0,0 +1,163 @@
using System;
using System.Text;
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.hexLogger
{
[TestClass]
[TestSubject(typeof(HexFormatter))]
public class HexFormatterTest
{
// -----------------------------
// ToHex(byte)
// -----------------------------
[TestMethod]
public void ToHex_FormatsSingleByte()
{
var result = HexFormatter.ToHex(0x0D);
Assert.AreEqual("0x0D", result);
}
// -----------------------------
// ToHex(byte[])
// -----------------------------
[TestMethod]
public void ToHex_FormatsByteArray()
{
byte[] data = { 0x01, 0x0D, 0xFF };
var result = HexFormatter.ToHex(data);
Assert.AreEqual("0x01 0x0D 0xFF", result);
}
[TestMethod]
public void ToHex_EmptyArray_ReturnsEmptyMarker()
{
var result = HexFormatter.ToHex(Array.Empty<byte>());
Assert.AreEqual("<empty>", result);
}
[TestMethod]
public void ToHex_Null_ReturnsEmptyMarker()
{
var result = HexFormatter.ToHex(null);
Assert.AreEqual("<empty>", result);
}
// -----------------------------
// ToSerialHex(byte[])
// -----------------------------
[TestMethod]
public void ToSerialHex_FormatsCorrectly()
{
byte[] data = { 0x0D, 0x04, 0x08, 0x01, 0x00, 0x1A };
var result = HexFormatter.ToSerialHex(data);
Assert.AreEqual("0D 04 08 01 00 1A", result);
}
[TestMethod]
public void ToSerialHex_Empty_ReturnsEmptyString()
{
var result = HexFormatter.ToSerialHex(Array.Empty<byte>());
Assert.AreEqual(string.Empty, result);
}
// -----------------------------
// ToHexWithAscii(byte)
// -----------------------------
[TestMethod]
public void ToHexWithAscii_PrintableAscii()
{
var result = HexFormatter.ToHexWithAscii(0x41); // 'A'
Assert.AreEqual("0x41 ('A')", result);
}
[TestMethod]
public void ToHexWithAscii_ControlChar()
{
var result = HexFormatter.ToHexWithAscii(0x0D); // CR
Assert.AreEqual("0x0D ('.')", result);
}
// -----------------------------
// ToSerialHexWithAscii(byte[])
// -----------------------------
[TestMethod]
public void ToSerialHexWithAscii_MixedData()
{
byte[] data = Encoding.ASCII.GetBytes("OK\r\n");
var result = HexFormatter.ToSerialHexWithAscii(data);
Assert.AreEqual("4F 4B 0D 0A | OK..", result);
}
// -----------------------------
// IntToBytesBE
// -----------------------------
[TestMethod]
public void IntToBytesBE_TwoBytes()
{
var result = HexFormatter.IntToBytesBE(0x1234, 2);
CollectionAssert.AreEqual(
new byte[] { 0x12, 0x34 },
result
);
}
// -----------------------------
// IntToBytesLE
// -----------------------------
[TestMethod]
public void IntToBytesLE_TwoBytes()
{
var result = HexFormatter.IntToBytesLE(0x1234, 2);
CollectionAssert.AreEqual(
new byte[] { 0x34, 0x12 },
result
);
}
// -----------------------------
// AsciiToBytes
// -----------------------------
[TestMethod]
public void AsciiToBytes_ConvertsString()
{
var result = HexFormatter.AsciiToBytes("AB");
CollectionAssert.AreEqual(
new byte[] { 0x41, 0x42 },
result
);
}
[TestMethod]
public void AsciiToBytes_EmptyString_ReturnsEmpty()
{
var result = HexFormatter.AsciiToBytes(string.Empty);
Assert.AreEqual(0, result.Length);
}
[TestMethod]
public void AsciiToBytes_Null_ReturnsEmpty()
{
var result = HexFormatter.AsciiToBytes(null);
Assert.AreEqual(0, result.Length);
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.led;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
{
[TestClass]
[TestSubject(typeof(ShortVariableLedParser))]
public class ShortVariableLedParserTest
{
[TestMethod]
public void Parse_ValidShortVariableMessage()
{
// Arrange
string raw = ";12345678,00012345.67;";
var message = new TouchReadLedMessage(raw);
var parser = new ShortVariableLedParser();
// Act
TouchReadLedData data = parser.Parse(message);
// Assert
Assert.IsNotNull(data);
Assert.AreEqual(raw, data.Raw);
Assert.AreEqual("12345678", data.MeterId);
Assert.AreEqual(12345.67m, data.Reading);
}
[TestMethod]
[ExpectedException(typeof(FormatException))]
public void Parse_InvalidDecimal_Throws()
{
// Arrange
string raw = ";12345678,ABCDEF;";
var message = new TouchReadLedMessage(raw);
var parser = new ShortVariableLedParser();
// Act
parser.Parse(message);
}
}
}

View File

@ -0,0 +1,46 @@
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.led;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.led
{
[TestClass]
[TestSubject(typeof(TouchReadLedMessage))]
public class TouchReadLedMessageTest
{
[TestMethod]
public void Parse_LedMessage_Basic()
{
string raw = ";12345678,00012345.67;";
var msg = new TouchReadLedMessage(raw);
Assert.AreEqual(2, msg.Fields.Length);
Assert.AreEqual("12345678", msg.Fields[0]);
Assert.AreEqual("00012345.67", msg.Fields[1]);
}
[TestMethod]
public void TouchReadLedData_Parse_Extended()
{
string raw = ";12345678,ABC123,00012345.67,m3;";
var msg = new TouchReadLedMessage(raw);
var data = new TouchReadLedData(raw)
{
MeterId = msg.Fields[0],
CustomerId = msg.Fields[1],
Reading = TouchReadLedData.ParseDecimal(msg.Fields[2]),
Units = msg.Fields[3]
};
Assert.AreEqual("12345678", data.MeterId);
Assert.AreEqual("ABC123", data.CustomerId);
Assert.AreEqual(12345.67m, data.Reading);
Assert.AreEqual("m3", data.Units);
}
}
}

View File

@ -0,0 +1,124 @@
using System;
using System.IO.Ports;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.wiredProtocol;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
{
[TestClass]
public class TouchReadBaudRateDetectionTests
{
private const string ComPort = "COM3"; // COM PORT OF THE ASIC
private const int ReadTimeoutMs = 1500;
private static readonly int[] StandardBaudRates =
{
115200, 9600//, 10400, 15625, 18432, 19200, 31250, 36864,
//38400, 50000, 57600, 62500, 76800,
//1200, 2400, 4800, 7812
};
[TestMethod]
[TestCategory("Hardware")]
[TestCategory("Serial")]
public void Detect_BaudRate_By_ViewFactoryId()
{
byte[] request = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.Simple)
.BuildBytes();
var parser = new TouchReadFrameParser();
foreach (int baud in StandardBaudRates)
{
Console.WriteLine($"--- Testing baud rate: {baud} ---");
try
{
using (var port = new SerialPort(ComPort, baud, Parity.None, 8, StopBits.One))
{
port.ReadTimeout = ReadTimeoutMs;
port.WriteTimeout = 500;
port.Open();
port.DiscardInBuffer();
port.DiscardOutBuffer();
Console.WriteLine("TX → " + HexFormatter.ToSerialHex(request));
port.Write(request, 0, request.Length);
byte[] response = ReadFullFrame(port);
Console.WriteLine("RX ← " + HexFormatter.ToSerialHex(response));
TouchReadResponse decoded = parser.Parse(response);
if (decoded.IsOk)
{
string factoryId = decoded.GetAsciiPayload();
Console.WriteLine();
Console.WriteLine("VALID RESPONSE");
Console.WriteLine("Baud rate : " + baud);
Console.WriteLine("Factory ID : " + factoryId);
Console.WriteLine();
Assert.IsFalse(string.IsNullOrEmpty(factoryId),
"Factory ID is empty");
return; // SUCCESS → stop scanning
}
}
}
catch (TimeoutException)
{
Console.WriteLine("Timeout");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
Assert.Fail("No valid baud rate detected.");
}
private static byte[] ReadFullFrame(SerialPort port)
{
byte start = (byte)port.ReadByte();
if (start != 0x0D)
throw new InvalidOperationException("Invalid START byte");
byte length = (byte)port.ReadByte();
int remaining = length;
byte[] buffer = new byte[2 + remaining];
buffer[0] = start;
buffer[1] = length;
int offset = 2;
while (remaining > 0)
{
int read = port.Read(buffer, offset, remaining);
offset += read;
remaining -= read;
}
return buffer;
}
[TestMethod]
public void ConvertTest()
{
byte[] input = { 0x53, 0x57, 0x05, 0x01, 0x0D };
Console.WriteLine(HexFormatter.ToSerialHex(input));
Console.WriteLine(HexFormatter.ToHex(input));
}
}
}

View File

@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.hexLogger;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.wiredProtocol;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication.C4.wiredProtocol
{
[TestClass]
[TestSubject(typeof(TouchReadFrameBuilder))]
public class TouchReadFrameBuilderTest
{
[TestMethod]
public void Encode_ViewFactoryId_Command()
{
byte[] frame = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewFactoryId)
.BuildBytes();
byte[] expected =
{
0x0D, // START
0x04, // LEN
0x08, // CONTROL (RF)
0x01, // COMMAND
0x00, // CHECKSUM HI
0x1A // CHECKSUM LO
};
CollectionAssert.AreEqual(expected, frame);
string log = TouchReadLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: < {0} >", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_ViewProgrammableId_Command()
{
byte[] frame = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewProgrammableId)
.BuildBytes();
byte[] expected =
{
0x0D, // START
0x04, // LEN
0x08, // CONTROL (RF)
0x03, // COMMAND
0x00, // CHECKSUM HI
0x1C // CHECKSUM LO
};
CollectionAssert.AreEqual(expected, frame);
string log = TouchReadLogger.DescribeTx(frame);
Console.WriteLine(log);
Console.WriteLine(@"Raw: <{0}>", HexFormatter.ToSerialHex(frame));
}
[TestMethod]
public void Encode_SetState_Idle()
{
// Arrange
byte[] frame = new TouchReadFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddPayload(new byte[] { 0x01 }) // Idle
.BuildBytes();
byte[] expected =
{
0x0D, // START
0x05, // LEN
0x08, // CONTROL (RF)
0x1A, // COMMAND (Set State)
0x01, // PAYLOAD (Idle)
0x00, // CHECKSUM HI
0x35 // CHECKSUM LO
};
// Assert
CollectionAssert.AreEqual(expected, frame,
$"Encoded frame mismatch.\nExpected: {HexFormatter.ToSerialHex(expected)}\nActual: {HexFormatter.ToSerialHex(frame)}");
}
[TestMethod]
[ExpectedException(typeof(FormatException))]
public void Decode_InvalidStart_Throws()
{
byte[] response =
{
0x00, // invalid START
0x04,
0x00,
0x01,
0x00,
0x12
};
var parser = new TouchReadFrameParser();
parser.Parse(response);
}
[TestMethod]
public void BuildBytes()
{
// Reserve space for checksum at [0] and [1]
var frame = new List<byte>
{
0x00, // checksum high (placeholder)
0x00, // checksum low (placeholder)
0x05, // length
0x01, // command
0x0D // start
};
// Calculate checksum over payload only (skip checksum bytes)
ushort checksum = TouchReadFrameBuilder.CalculateChecksum(
frame.Skip(2)
);
// Write checksum into first two positions
frame[0] = (byte)(checksum >> 8); // high byte
frame[1] = (byte)(checksum & 0xFF); // low byte
Console.WriteLine(HexFormatter.ToHex(frame.ToArray()));
}
[TestMethod]
public void ByteConversion()
{
byte[] frame = { 0x53, 0x57,0x05, 0x01, 0x0D};
Console.WriteLine(@"1: " + HexFormatter.ToHex(frame.ToArray()));
byte[] payload = { 0x31, 0x30, 0x30, 0x31, 0x30, 0x34, 0x30, 0x35, 0x31, 0x00 };
Console.WriteLine(@"Payload: " + HexFormatter.ToSerialHexWithAscii(payload.ToArray()));
//Connect
//2026-02-04 14:06:22.515 TX (8) 53 57 3F 76 65 72 73 0D
//2026-02-04 14:06:22.906 RX (74) 3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20 56 3A 30 36 2E 30 36 2E 30 31 2C 20 46 57 3A 31 39 30 32 31 35 2C 20 37 45 43 45 2C 20 42 31 2E 36 2E 30 31 2C 20 48 57 3A 34 2C 20 53 65 72 69 61 6C 3A 30 0D
string msg = "53 57 3F 76 65 72 73 0D";
byte[] activationMsg = HexFormatter.HexStringToByteArray(msg);
Console.WriteLine(@"ActivationMsg MSG: " + HexFormatter.ToSerialHexWithAscii(activationMsg.ToArray()));
string str =
"3F 76 65 72 73 3A 20 48 61 72 72 79 20 54 3A 42 38 30 30 2C 20 56 3A 30 36 2E 30 36 2E 30 31 2C 20 46 57 3A 31 39 30 32 31 35 2C 20 37 45 43 45 2C 20 42 31 2E 36 2E 30 31 2C 20 48 57 3A 34 2C 20 53 65 72 69 61 6C 3A 30 0D";
byte[] activationMsgRes = HexFormatter.HexStringToByteArray(str);
Console.WriteLine(@"ActivationMsg RES: " + HexFormatter.ToSerialHexWithAscii(activationMsgRes.ToArray()));
}
}
}

View File

@ -0,0 +1,22 @@
using JetBrains.Annotations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TBF.Rig.TestMethods.iPerlCommunication.communication;
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
namespace TBFTests.Rig.RegisterReaders.iPerlASICReader.communication
{
[TestClass]
[TestSubject(typeof(OptoHeadTest))]
public class OptoHeadTestTest
{
[TestMethod]
public void ReadRequest_PCB_Test()
{
IperlHead iHead = new IperlHead();
OptoHeadTest.ReadRequest_PCB(ref iHead);
}
}
}