From 2fd2697e3b1ac8d422dd9f317506f9a5d8336a53 Mon Sep 17 00:00:00 2001 From: Michal Buzik Date: Mon, 17 Aug 2026 10:25:35 +0200 Subject: [PATCH] Fix lost 3.9.2204.0 versioning and improve Poseidon CLI diagnostics - restore the Morrisville release version metadata - add end-to-end logs for CLI execution, reader state, parsed results, and UI updates - prevent completed Poseidon reads from being started repeatedly in a cycle - use a fixed CLI directory and reliable working directory --- TBF/Properties/AssemblyInfo.cs | 4 +-- TBF/Rig/DataEntry/PoseidonCmd/EntryForm.cs | 16 ++++++++-- .../DataEntry/PoseidonCmd/TestStartEndForm.cs | 9 ++++++ .../PoseidonCmdStartStop/CliRunner.cs | 4 ++- .../PoseidonCmdStartStop/PoseidonReader.cs | 9 ++++++ .../PoseidonCmdStartStop/SerialPortData.cs | 26 ++++++++++++----- .../PoseidonCmdStartStop/CliRunnerTest.cs | 29 ++++++++++++++----- 7 files changed, 76 insertions(+), 21 deletions(-) diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index bf349a390..be61ee32a 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.2203.1")] -[assembly: AssemblyFileVersion("3.9.2203.1")] +[assembly: AssemblyVersion("3.9.2204.1")] +[assembly: AssemblyFileVersion("3.9.2204.1")] diff --git a/TBF/Rig/DataEntry/PoseidonCmd/EntryForm.cs b/TBF/Rig/DataEntry/PoseidonCmd/EntryForm.cs index 5975229b3..95901aeb2 100644 --- a/TBF/Rig/DataEntry/PoseidonCmd/EntryForm.cs +++ b/TBF/Rig/DataEntry/PoseidonCmd/EntryForm.cs @@ -444,15 +444,26 @@ namespace TBF.Rig.DataEntry.PoseidonCmd if(poseidonReader == null) continue; poseidonReader.SetCliLogging(CliLogging); - if (!(poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.ReadDatastream_Done - || poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.ReadDatastream_Running)) + // Start a read only once. The previous condition restarted a + // reader after it reached Done/Error, which kept the dialog in + // Loading... and repeatedly launched the CLI for every meter. + if (poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.None) { + log.DebugFormat("Poseidon read: starting {0} for {1}", currentOp, poseidonReader.Name); poseidonReader.SetCurrentOp((currentOp == CurrentOp.ReadDatastream_StartStates)? PoseidonReader.CurrentPoseidonOp.ReadDataStream_Start : PoseidonReader.CurrentPoseidonOp.ReadDataStream_End); } /// Send start data stream poseidonReader.Run(); + if (poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Error) + { + log.ErrorFormat("Poseidon read: {0} completed with Error during {1}", poseidonReader.Name, currentOp); + } + else if (poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Done) + { + log.DebugFormat("Poseidon read: {0} completed during {1}", poseidonReader.Name, currentOp); + } if (!(poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Done || poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Error)) { @@ -462,6 +473,7 @@ namespace TBF.Rig.DataEntry.PoseidonCmd } if (bAllReadersFinished) { + log.DebugFormat("Poseidon read: all readers finished for {0}", currentOp); finishedReading = true; } else diff --git a/TBF/Rig/DataEntry/PoseidonCmd/TestStartEndForm.cs b/TBF/Rig/DataEntry/PoseidonCmd/TestStartEndForm.cs index 5087090fc..f2b2f465b 100644 --- a/TBF/Rig/DataEntry/PoseidonCmd/TestStartEndForm.cs +++ b/TBF/Rig/DataEntry/PoseidonCmd/TestStartEndForm.cs @@ -144,6 +144,9 @@ namespace TBF.Rig.DataEntry.PoseidonCmd private void SetUiBusy(bool busy, long deltaTime = -1) { + log.DebugFormat("Poseidon UI: SetUiBusy busy={0}, deltaTime={1}, enabledTextBoxes={2}", + busy, deltaTime, enabledTextBoxes.Count); + // show wait cursor for form and children this.UseWaitCursor = busy; @@ -290,10 +293,15 @@ namespace TBF.Rig.DataEntry.PoseidonCmd // Ensure we are on the UI thread if (InvokeRequired) { + log.DebugFormat("Poseidon UI: queue UpdateValues startValue={0}, enableEdit={1}, deltaTime={2}", + stratValue, enableEdit, deltaTime); BeginInvoke(new Action(() => UpdateValues(stratValue, enableEdit))); return; } + log.DebugFormat("Poseidon UI: UpdateValues on UI thread startValue={0}, enableEdit={1}, deltaTime={2}", + stratValue, enableEdit, deltaTime); + for (int i = 0; i < TextBoxesCount; i++) { if (stratValue) @@ -317,6 +325,7 @@ namespace TBF.Rig.DataEntry.PoseidonCmd if (enableEdit) { SetUiBusy(false, deltaTime); + log.Debug("Poseidon UI: values applied and dialog released from Loading..."); } // if you also need to enable/disable editing, do it here, // it's now safely on the UI thread. diff --git a/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunner.cs b/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunner.cs index 3346e7105..31473d2ba 100644 --- a/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunner.cs +++ b/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunner.cs @@ -222,6 +222,7 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop { FileName = fileName, Arguments = args, + WorkingDirectory = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(fileName)), RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, @@ -314,6 +315,7 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop { FileName = fileName, Arguments = args, + WorkingDirectory = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(fileName)), RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, @@ -471,4 +473,4 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop }); } } -} \ No newline at end of file +} diff --git a/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/PoseidonReader.cs b/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/PoseidonReader.cs index 4e3d30588..90318b0cb 100644 --- a/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/PoseidonReader.cs +++ b/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/PoseidonReader.cs @@ -411,6 +411,11 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop CliRunner.Clear(); _lastOpTimedOut = false; + log.DebugFormat("{0}: starting CLI read, direction={1}, path='{2}', args='{3}'", + Name, + _isReadingStart ? "start" : "end", + serialPort == null ? "" : serialPort.SerialPortCmdClientPath, + serialPort == null ? "" : serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams)); CliRunner.AddRunAndCaptureJsonAsync(serialPort, SerialPortData.EMeterArg.AllParams); _currentOp = CurrentPoseidonOp.ReadDatastream_Running; @@ -422,6 +427,8 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop { _currentOp = CurrentPoseidonOp.ReadDatastream_Done; incommingTime = CliRunner.IncommingTime; + log.DebugFormat("{0}: CLI read task finished, taskCount={1}, incomingTime={2}", + Name, CliRunner.TaskPool.Count, incommingTime); } else if (CliRunner.TimeOutReceived(SafetyTimeOut)) { @@ -462,6 +469,8 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop if (data != null) { + log.DebugFormat("{0}: CLI read result deviceId={1}, reading={2}, readingComplete={3}, nfcTagDetected={4}", + Name, data.DeviceId, data.Reading, data.ReadingComplete, data.NfcTagDetected); if (string.IsNullOrEmpty(wmSerialNr)) { try diff --git a/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/SerialPortData.cs b/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/SerialPortData.cs index 786179c14..5d7261e08 100644 --- a/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/SerialPortData.cs +++ b/TBF/Rig/RegisterReaders/PoseidonCmdStartStop/SerialPortData.cs @@ -8,6 +8,8 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop { public class SerialPortData { + public const string CliDirectory = @"C:\TBF\Cli"; + private Boolean? _cliExists; public bool CliExists { get { if (_cliExists == null || !_cliExists.HasValue) @@ -16,13 +18,21 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop } return _cliExists.Value; } } - public string SerialPortCmdClientPath { -#if DEBUG - get { return Path.Combine("C:\\","TBF","Cli", CmdClientName);} -#else - get { return Path.Combine("C:\\","TBF","Cli", CmdClientName);} -#endif - } + public string SerialPortCmdClientPath + { + get + { + // The configured value is a file name, not an executable path. + // Keeping the CLI directory fixed prevents a bench configuration + // from starting an unintended executable or failing due to a + // relative path/current-directory change. + string cliFileName = Path.GetFileName(CmdClientName); + if (string.IsNullOrWhiteSpace(cliFileName)) + cliFileName = "HalCli.exe"; + + return Path.Combine(CliDirectory, cliFileName); + } + } public string CmdClientName { get; set; } = "HalCli.exe"; public string PortName { get; set; } // Backward compatibility: old numeric meter type @@ -259,4 +269,4 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop } -} \ No newline at end of file +} diff --git a/TBFTests/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunnerTest.cs b/TBFTests/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunnerTest.cs index 357ccfcf2..80082ff9b 100644 --- a/TBFTests/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunnerTest.cs +++ b/TBFTests/Rig/RegisterReaders/PoseidonCmdStartStop/CliRunnerTest.cs @@ -66,7 +66,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams); Assert.AreEqual( - "-p COM3 -m Poseidon --hat mth --timeout 10 --operation readall", + "-p COM3 -m 74 --hat mth --timeout 10 --operation readall", args); } @@ -83,7 +83,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop string args = serialPort.DefaultArgSettings(SerialPortData.EMeterArg.DeviceId); Assert.AreEqual( - "-p COM3 -m Poseidon --hat harry --timeout 30 --operation read --parameter DeviceId", + "-p COM3 -m 74 --hat harry --timeout 30 --operation read --parameter DeviceId", args); } @@ -104,7 +104,7 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop { var testCases = new[] { - new { Meter = SerialPortData.MeterProduct.Poseidon, Expected = "Poseidon" }, + new { Meter = SerialPortData.MeterProduct.Poseidon, Expected = "74" }, new { Meter = SerialPortData.MeterProduct.Ally, Expected = "ally" }, new { Meter = SerialPortData.MeterProduct.IperlPlus, Expected = "iperlplus" }, new { Meter = SerialPortData.MeterProduct.IperlLegacy, Expected = "iperllegacy" } @@ -133,25 +133,38 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop serialPort.Macro = "readmacro1"; Assert.AreEqual( - "-p COM3 -m Poseidon --hat mth --timeout 10 --operation readmacro1", + "-p COM3 -m 74 --hat mth --timeout 10 --operation readmacro1", serialPort.DefaultArgSettings(SerialPortData.EMeterArg.ReadMacro1)); serialPort.Macro = "readmacro2"; Assert.AreEqual( - "-p COM3 -m Poseidon --hat mth --timeout 10 --operation readmacro2", + "-p COM3 -m 74 --hat mth --timeout 10 --operation readmacro2", serialPort.DefaultArgSettings(SerialPortData.EMeterArg.ReadMacro2)); serialPort.Macro = "readmacro3"; Assert.AreEqual( - "-p COM3 -m Poseidon --hat mth --timeout 10 --operation readmacro3", + "-p COM3 -m 74 --hat mth --timeout 10 --operation readmacro3", serialPort.DefaultArgSettings(SerialPortData.EMeterArg.ReadMacro3)); serialPort.Macro = "xxx"; Assert.AreEqual( - "-p COM3 -m Poseidon --hat mth --timeout 10 --operation xxx", + "-p COM3 -m 74 --hat mth --timeout 10 --operation xxx", serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams)); } + [TestMethod] + public void SerialPortData_CliPath_ShouldAlwaysUseFixedCliDirectory() + { + SerialPortData serialPort = new SerialPortData( + "COM3", + @"D:\obsolete\HatCliDemo.exe", + SerialPortData.MeterProduct.Poseidon); + + Assert.AreEqual( + @"C:\TBF\Cli\HatCliDemo.exe", + serialPort.SerialPortCmdClientPath); + } + [TestMethod] public void RunMultipleTimesTestProgram_CheckParalelWork() { @@ -445,4 +458,4 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop } } -} \ No newline at end of file +}