diff --git a/Common/Iperl/OptoTelegramRaw.cs b/Common/Iperl/OptoTelegramRaw.cs
index 6a51f94cf..effeceaa7 100644
--- a/Common/Iperl/OptoTelegramRaw.cs
+++ b/Common/Iperl/OptoTelegramRaw.cs
@@ -56,7 +56,7 @@ namespace Common.Iperl
public double Flow(double scalingFactor) { return 0.225 * scalingFactor * (double)FlowRaw; }
public double Volume(double scalingFactor) { return 0.0000625 * scalingFactor * (double)VolumeRawExt; }
public Int32 FlipTime() { return Impedance; }
- public decimal TimestampDec() { return (decimal)TimestampExt / (decimal)8192; }
+ public decimal TimestampDec() { return (decimal)TimestampExt; }
public double VolumeDelta(double scalingFactor, OptoTelegramRaw previous) { return (previous == null) ? 0 : Volume(scalingFactor) - previous.Volume(scalingFactor); }
public decimal TimeDelta() { return TimestampDec() - TestStartTimestampDec; }
public string Label()
diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs
index 0c99cc150..8bdd46065 100644
--- a/TBF/Properties/AssemblyInfo.cs
+++ b/TBF/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
-[assembly: AssemblyVersion("3.9.3065.1")]
-[assembly: AssemblyFileVersion("3.9.3065.1")]
+[assembly: AssemblyVersion("3.9.3066.1")]
+[assembly: AssemblyFileVersion("3.9.3066.1")]
diff --git a/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs b/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs
index 22acd7cbc..9ef2e4d5b 100644
--- a/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs
+++ b/TBF/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRaw.cs
@@ -58,7 +58,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.common
public double Flow(double scalingFactor) { return 0.225 * scalingFactor * (double)FlowRaw; }
public double Volume(double scalingFactor) { return 0.0000625 * scalingFactor * (double)VolumeRawExt; }
public Int32 FlipTime() { return Impedance; }
- public decimal TimestampDec() { return (decimal)TimestampExt / (decimal)8192; }
+
+ public decimal TimestampDec() { return (decimal)TimestampExt;}
public double VolumeDelta(double scalingFactor, OptoTelegramRaw previous) { return (previous == null) ? 0 : Volume(scalingFactor) - previous.Volume(scalingFactor); }
public decimal TimeDelta() { return TimestampDec() - TestStartTimestampDec; }
public string Label()
@@ -330,9 +331,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.common
(EmfRaw & 0x00FFFFFF).ToString("X6"),
MagneticFieldRaw.ToString("X4"),
FlowRaw.ToString("X4"),
- VolumeRaw.ToString("X6"),
+ VolumeRaw.ToString("F4", culture),
Impedance.ToString("X4"),
- Timestamp.ToString("X8"),
+ Timestamp.ToString("F4", culture),
CheckSum.ToString("X2"),
EMF().ToString("F4", culture),
MagneticField().ToString("F0", culture),
diff --git a/TBFTests/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRawTest.cs b/TBFTests/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRawTest.cs
new file mode 100644
index 000000000..30a66b7d4
--- /dev/null
+++ b/TBFTests/Rig/TestMethods/iPerlCommunication/common/OptoTelegramRawTest.cs
@@ -0,0 +1,350 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using TBF.Rig.TestMethods.iPerlCommunication.common;
+using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer;
+
+namespace TBFTests.Rig.TestMethods.iPerlCommunication.common
+{
+ [TestClass]
+ public class OptoTelegramRawTest
+ {
+ private static DiagnosticLedState7Data CreateDiagnosticLedState7Data(
+ double volumeLiters,
+ double timeSeconds,
+ short rawFlow = 0)
+ {
+ uint rawVolumeTicks = (uint)Math.Round(volumeLiters / 0.00025);
+ uint timestampTicks = (uint)Math.Round(timeSeconds * 8192.0);
+
+ string[] fields =
+ {
+ "000000",
+ "0000",
+ ((ushort)rawFlow).ToString("X4"),
+ rawVolumeTicks.ToString("X6"),
+ "0000",
+ "0000",
+ timestampTicks.ToString("X8"),
+ "00",
+ "00000000",
+ "0000",
+ "0000",
+ "0000",
+ "0000",
+ "00",
+ "0000",
+ "0000",
+ "00",
+ "00",
+ "00000000",
+ "00",
+ "000000",
+ "000000",
+ "0000",
+ "0000",
+ "00",
+ "00"
+ };
+
+ string rawLine = string.Join("\t", fields) + "\r\n";
+ return new DiagnosticLedState7Data(rawLine, fields);
+ }
+
+ [TestMethod]
+ public void UpdateFromSmart_FirstSample_ShouldInitializeFields()
+ {
+ var telegram = new OptoTelegramRaw();
+ var data = CreateDiagnosticLedState7Data(
+ volumeLiters: 2.5,
+ timeSeconds: 100.0);
+
+ double lastVolume = double.NaN;
+ double lastTimestamp = double.NaN;
+
+ telegram.UpdateFromSmart(data, counter: 7, refFlow: 1.5f, ref lastVolume, ref lastTimestamp);
+
+ Assert.AreEqual(7, telegram.Counter);
+ Assert.AreEqual(1.5f, telegram.RefFlow);
+ Assert.AreEqual(OptoTelegramFlags.OK, telegram.Flags);
+
+ Assert.AreEqual(2.5, telegram.VolumeRaw, 1e-9);
+ Assert.AreEqual(2.5, telegram.VolumeRawExt, 1e-9);
+ Assert.AreEqual(2.5, lastVolume, 1e-9);
+
+ Assert.AreEqual(100.0, telegram.Timestamp, 1e-9);
+ Assert.AreEqual(100.0, telegram.TimestampExt, 1e-9);
+ Assert.AreEqual(100.0, lastTimestamp, 1e-9);
+
+ Assert.AreNotEqual(default(DateTime), telegram.DateTime);
+ Assert.AreEqual(0, telegram.FlowRaw);
+ Assert.AreEqual(0, telegram.CheckSum);
+ Assert.AreEqual(0, telegram.Impedance);
+ Assert.AreEqual(0, telegram.EmfRaw);
+ Assert.AreEqual(0, telegram.MagneticFieldRaw);
+ }
+
+ [TestMethod]
+ public void UpdateFromSmart_RealDecodedSample_ShouldMapExpectedValues()
+ {
+ var telegram = new OptoTelegramRaw();
+
+ var data = CreateDiagnosticLedState7Data(
+ volumeLiters: 0.48025,
+ timeSeconds: 62727.0);
+
+ double lastVolume = double.NaN;
+ double lastTimestamp = double.NaN;
+
+ telegram.UpdateFromSmart(data, counter: 1, refFlow: 0.0f, ref lastVolume, ref lastTimestamp);
+
+ Assert.AreEqual(1, telegram.Counter);
+ Assert.AreEqual(0.0f, telegram.RefFlow);
+ Assert.AreEqual(OptoTelegramFlags.OK, telegram.Flags);
+
+ Assert.AreEqual(0.48025, telegram.VolumeRaw, 1e-9);
+ Assert.AreEqual(0.48025, telegram.VolumeRawExt, 1e-9);
+ Assert.AreEqual(0.48025, lastVolume, 1e-9);
+
+ Assert.AreEqual(62727.0, telegram.Timestamp, 1e-9);
+ Assert.AreEqual(62727.0, telegram.TimestampExt, 1e-9);
+ Assert.AreEqual(62727.0, lastTimestamp, 1e-9);
+ }
+
+ [TestMethod]
+ public void UpdateFromSmart_TimestampOverflow_ShouldKeepIncreasingExtendedTimestamp()
+ {
+ double lastVolumeExt = double.NaN;
+ double lastTimestampExt = double.NaN;
+
+ double[] times =
+ {
+ 524280.0,
+ 524287.0,
+ 1.0,
+ 2.0,
+ 10.0
+ };
+
+ double previousExt = double.NaN;
+
+ for (int i = 0; i < times.Length; i++)
+ {
+ var telegram = new OptoTelegramRaw();
+ var data = CreateDiagnosticLedState7Data(1.0, times[i]);
+
+ telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
+
+ if (!double.IsNaN(previousExt))
+ {
+ Assert.IsTrue(
+ telegram.TimestampExt >= previousExt,
+ $"Timestamp decreased at index {i}. Prev={previousExt}, Current={telegram.TimestampExt}");
+ }
+
+ previousExt = telegram.TimestampExt;
+ }
+ }
+
+ [TestMethod]
+ public void UpdateFromSmart_TimeDelta_ShouldNeverBeNegativeAcrossOverflow()
+ {
+ double lastVolumeExt = double.NaN;
+ double lastTimestampExt = double.NaN;
+
+ OptoTelegramRaw.TestStartTimestampDec = 524280m;
+
+ double[] times =
+ {
+ 524280.0,
+ 524287.0,
+ 1.0,
+ 2.0,
+ 10.0
+ };
+
+ decimal previousDelta = decimal.MinValue;
+
+ for (int i = 0; i < times.Length; i++)
+ {
+ var telegram = new OptoTelegramRaw();
+ var data = CreateDiagnosticLedState7Data(1.0, times[i]);
+
+ telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
+
+ decimal delta = telegram.TimeDelta();
+
+ Assert.IsTrue(delta >= 0, $"Negative TimeDelta at index {i}: {delta}");
+ Assert.IsTrue(delta >= previousDelta,
+ $"TimeDelta decreased at index {i}. Previous={previousDelta}, Current={delta}");
+
+ previousDelta = delta;
+ }
+ }
+
+ [TestMethod]
+ public void UpdateFromSmart_VolumeOverflow_ShouldKeepIncreasingExtendedVolume()
+ {
+ double lastVolumeExt = double.NaN;
+ double lastTimestampExt = double.NaN;
+
+ double volumeRange = 16777216.0 * 0.00025; // 4194.304 L
+
+ double[] volumes =
+ {
+ 4194.0,
+ 4194.25,
+ volumeRange + 0.25,
+ volumeRange + 1.0,
+ volumeRange + 2.0
+ };
+
+ double previousExt = double.NaN;
+
+ for (int i = 0; i < volumes.Length; i++)
+ {
+ var telegram = new OptoTelegramRaw();
+ var data = CreateDiagnosticLedState7Data(volumes[i], i);
+
+ telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
+
+ if (!double.IsNaN(previousExt))
+ {
+ Assert.IsTrue(
+ telegram.VolumeRawExt >= previousExt,
+ $"Volume decreased at index {i}. Prev={previousExt}, Current={telegram.VolumeRawExt}");
+ }
+
+ previousExt = telegram.VolumeRawExt;
+ }
+ }
+
+ [TestMethod]
+ public void SetFlags_ShouldChangeFlags()
+ {
+ var telegram = new OptoTelegramRaw();
+
+ telegram.SetFlags(OptoTelegramFlags.SyncError);
+
+ Assert.AreEqual(OptoTelegramFlags.SyncError, telegram.Flags);
+ }
+
+ [TestMethod]
+ public void Label_ShouldReturnExpectedText()
+ {
+ var telegram = new OptoTelegramRaw();
+
+ telegram.Flags = OptoTelegramFlags.OK_TestStart;
+ Assert.AreEqual("#### start test ####", telegram.Label());
+
+ telegram.Flags = OptoTelegramFlags.OK_TestEnd;
+ Assert.AreEqual("#### end of test ####", telegram.Label());
+
+ telegram.Flags = OptoTelegramFlags.OK;
+ Assert.AreEqual(string.Empty, telegram.Label());
+ }
+
+ [TestMethod]
+ public void TimestampDec_ShouldConvertCorrectly()
+ {
+ var telegram = new OptoTelegramRaw
+ {
+ TimestampExt = 8192.0
+ };
+
+ Assert.AreEqual(8192.0m, telegram.TimestampDec());
+ }
+
+ [TestMethod]
+ public void VolumeDelta_ShouldReturnDifferenceAgainstPrevious()
+ {
+ var previous = new OptoTelegramRaw { VolumeRawExt = 1000.0 };
+ var current = new OptoTelegramRaw { VolumeRawExt = 2000.0 };
+
+ double scalingFactor = 2.0;
+
+ double expectedPrevious = 0.0000625 * scalingFactor * 1000.0;
+ double expectedCurrent = 0.0000625 * scalingFactor * 2000.0;
+ double expectedDelta = expectedCurrent - expectedPrevious;
+
+ Assert.AreEqual(expectedDelta, current.VolumeDelta(scalingFactor, previous), 1e-12);
+ }
+
+ [TestMethod]
+ public void UpdateFromStringDummy_InvalidLength_ShouldReturnFalse_AndSetInvalidFlag()
+ {
+ var telegram = new OptoTelegramRaw();
+
+ bool result = telegram.UpdateFromStringDummy("short");
+
+ Assert.IsFalse(result);
+ Assert.AreEqual(OptoTelegramFlags.InvalidTelegram, telegram.Flags);
+ }
+
+ [TestMethod]
+ public void UpdateFromStringDummy_ValidFormatButWrongChecksum_ShouldReturnFalse_AndSetInvalidFlag()
+ {
+ var telegram = new OptoTelegramRaw();
+
+ string dummy = "FFFFFE\t51EA\t0000\t65324E\t0087\tF6319DFF\t00\r\n";
+
+ bool result = telegram.UpdateFromStringDummy(dummy);
+
+ Assert.IsFalse(result);
+ Assert.AreEqual(OptoTelegramFlags.InvalidTelegram, telegram.Flags);
+ }
+
+ [TestMethod]
+ public void ToString_WhenSyncError_ShouldReturnSynchronizationErrorText()
+ {
+ var telegram = new OptoTelegramRaw
+ {
+ Flags = OptoTelegramFlags.SyncError
+ };
+
+ string text = telegram.ToString(1.0, null);
+
+ Assert.AreEqual("Sychronization error", text);
+ }
+
+ [TestMethod]
+ public void ToString_WhenInvalidTelegram_ShouldReturnInvalidTelegramText()
+ {
+ var telegram = new OptoTelegramRaw
+ {
+ Flags = OptoTelegramFlags.InvalidTelegram
+ };
+
+ string text = telegram.ToString(1.0, null);
+
+ Assert.AreEqual("Invalid telegram", text);
+ }
+
+ [TestMethod]
+ public void ToString_WhenOk_ShouldContainCounterAndLabel()
+ {
+ var telegram = new OptoTelegramRaw
+ {
+ Flags = OptoTelegramFlags.OK_TestStart,
+ DateTime = new DateTime(2024, 1, 1, 10, 11, 12, 123),
+ Counter = 5,
+ EmfRaw = 1,
+ MagneticFieldRaw = 2,
+ FlowRaw = 3,
+ VolumeRaw = 4,
+ Impedance = 5,
+ Timestamp = 6,
+ CheckSum = 7,
+ VolumeRawExt = 1000,
+ TimestampExt = 8192,
+ RefFlow = 1.25f
+ };
+
+ OptoTelegramRaw.TestStartTimestampDec = 0m;
+
+ string text = telegram.ToString(2.0, null);
+
+ Assert.IsTrue(text.Contains("5 :"), "Counter should be present in output.");
+ Assert.IsTrue(text.Contains("#### start test ####"), "Label should be present in output.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/TBFTests/TBFTests.csproj b/TBFTests/TBFTests.csproj
index 69a472d5b..0dcbe63d1 100644
--- a/TBFTests/TBFTests.csproj
+++ b/TBFTests/TBFTests.csproj
@@ -9,7 +9,7 @@
Properties
TBFTests
TBFTests
- v4.7.2
+ v4.8
512
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10.0
@@ -19,6 +19,7 @@
UnitTest
+ 8
true
@@ -135,6 +136,7 @@
+
@@ -159,11 +161,10 @@
SchematicDrawing
- {8648FD92-CDA1-4C3A-B5F9-FE547CE1FA48}
+ {8648fd92-cda1-4c3a-b5f9-fe547ce1fa48}
TBF
-