From 93e207c2110ccb017f161e26d9724763bed4acea Mon Sep 17 00:00:00 2001 From: Michal Buzik Date: Thu, 2 Apr 2026 09:40:19 +0200 Subject: [PATCH] Update `GenesisSmartReader` for refined start/end marker logic, add `_endDeltaSeconds` property, and improve telegram index resolution methods. Increment assembly version to `3.9.3031.1`. --- TBF/Properties/AssemblyInfo.cs | 4 +- .../implementations/GenesisSmartReader.cs | 135 ++++++++++++++---- 2 files changed, 108 insertions(+), 31 deletions(-) diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 4891e220b..5b1ffbc57 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("3.9.3030.1")] -[assembly: AssemblyFileVersion("3.9.3030.1")] +[assembly: AssemblyVersion("3.9.3031.1")] +[assembly: AssemblyFileVersion("3.9.3031.1")] diff --git a/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs b/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs index ab81d0415..6b67fc7c9 100644 --- a/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs +++ b/TBF/Rig/RegisterReaders/GenesisRegReader/implementations/GenesisSmartReader.cs @@ -678,6 +678,14 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations OptoTelegramRaw[] optoData; int optoDataCount; + private double _endDeltaSeconds = 1.0; + + public double EndDeltaSeconds + { + get => _endDeltaSeconds; + set => _endDeltaSeconds = value < 0 ? 0 : value; + } + /// Real opto deta count, can be larger then optoData.Length /// OptoTelegramRaw toBeFlushed; @@ -984,24 +992,26 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations timeFromStart += StateMachine.Period; ReadPulses(); - // Start sample after 1 second - if (!startSampleAcquired && (timeFromStart >= 1) && (currentTelegramIx >= 0)) + if (TestStartTelegramIx < 0) { - startSampleAcquired = true; - TestStartTelegramIx = currentTelegramIx; - - // initialize end at the same point - TestEndTelegramIx = currentTelegramIx; - - log.DebugFormat( - "Test start acquired at ix={0}, timeFromStart={1}", - TestStartTelegramIx, - timeFromStart); + TestStartTelegramIx = FindFirstValidTelegramIx(); + if (TestStartTelegramIx >= 0) + { + log.DebugFormat("TestStartTelegramIx set to first valid sample: {0}", TestStartTelegramIx); + } } - else if (startSampleAcquired && currentTelegramIx >= 0) + + if (optoDataCount > 0) { - // always keep latest telegram as end - TestEndTelegramIx = currentTelegramIx; + TestEndTelegramIx = FindEndTelegramIxByMeterTime(_endDeltaSeconds); + + if (TestEndTelegramIx >= 0) + { + log.DebugFormat( + "TestEndTelegramIx set by meter time: {0}, delta={1:F3}s", + TestEndTelegramIx, + _endDeltaSeconds); + } } } @@ -1020,35 +1030,28 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations lock (this) { - // 1. stop new reads from serial StopOptoReadLoop(); - - // 2. clear data stream processing - ClearReceivedLines();//Empty othrs - // 2. process everything already queued - //DrainQueuedLines(); - + ClearReceivedLines(); ResetDataBuffer(); - - // 3. now it is safe to close the port CloseOptoSerialPort(); - // 4. mark state as stopped dataStreamState = DataStreamState.Flush; startDataProcessing = false; - // 5. add marks using fully processed data + if (TestStartTelegramIx < 0) + TestStartTelegramIx = FindFirstValidTelegramIx(); + + TestEndTelegramIx = FindEndTelegramIxByMeterTime(_endDeltaSeconds); + AddTestStartEndMarksToData(out startIx, out endIx); } DataStreamPostProcessing(); - - log.WarnFormat("Genesis.Stop() startIx={0} endIx={1} len={2} no raw data file", startIx, endIx, optoData.Length); - if (TestStartTelegramIx == 0 || optoDataCount < 100) + if (TestStartTelegramIx < 0 || TestEndTelegramIx < 0 || optoDataCount < 100) { ResultCode |= (int)Results.Entities.ResultCode.MissingOptoData; } @@ -1058,6 +1061,80 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations } } + private int FindFirstValidTelegramIx() + { + for (int i = 0; i < optoDataCount; i++) + { + int wrappedIx = BufferIdx(i); + var record = optoData[wrappedIx]; + + if (IsValidVolumeRecord(record)) + return i; + } + + return -1; + } + + private double FindLastMeterTimestamp() + { + double maxTs = double.NaN; + + for (int i = 0; i < optoDataCount; i++) + { + int wrappedIx = BufferIdx(i); + var record = optoData[wrappedIx]; + + if (!IsValidVolumeRecord(record)) + continue; + + if (double.IsNaN(maxTs) || record.TimestampExt > maxTs) + maxTs = record.TimestampExt; + } + + return maxTs; + } + + private int FindEndTelegramIxByMeterTime(double endDeltaSeconds) + { + if (optoDataCount <= 0) + return -1; + + double lastTime = FindLastMeterTimestamp(); + if (double.IsNaN(lastTime)) + return -1; + + double targetTime = lastTime - endDeltaSeconds; + int foundIx = -1; + + for (int i = 0; i < optoDataCount; i++) + { + int wrappedIx = BufferIdx(i); + var record = optoData[wrappedIx]; + + if (!IsValidVolumeRecord(record)) + continue; + + if (record.TimestampExt <= targetTime) + { + foundIx = i; + } + } + + // fallback: if delta is too large and nothing matches, use last valid record + if (foundIx < 0) + { + for (int i = optoDataCount - 1; i >= 0; i--) + { + int wrappedIx = BufferIdx(i); + var record = optoData[wrappedIx]; + + if (IsValidVolumeRecord(record)) + return i; + } + } + + return foundIx; + } private volatile bool _stopQueueData = false;