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:
parent
c30e8540b2
commit
6d959ddf96
@ -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">
|
||||
<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: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>
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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()));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user