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
This commit is contained in:
Michal Buzik 2026-08-17 10:25:35 +02:00
parent f51fd4709e
commit 2fd2697e3b
7 changed files with 76 additions and 21 deletions

View File

@ -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")]

View File

@ -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

View File

@ -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.

View File

@ -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
});
}
}
}
}

View File

@ -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 ? "<not initialized>" : serialPort.SerialPortCmdClientPath,
serialPort == null ? "<not initialized>" : serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams));
CliRunner.AddRunAndCaptureJsonAsync<JsonDataFromPoseidon>(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

View File

@ -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
}
}
}

View File

@ -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
}
}
}
}