Poseidon - merge project
This commit is contained in:
parent
8d42232589
commit
b8e54e1fc9
@ -41,6 +41,8 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
|
||||
|
||||
System.Windows.Forms.Form modelessDlg;
|
||||
bool modelessDialogOpening;
|
||||
bool modelessDialogWaitLogged;
|
||||
public bool Completed { get { return (modelessDlg is IHasCompleted) ? (modelessDlg as IHasCompleted).Completed : true; } }
|
||||
|
||||
double refVolume;
|
||||
@ -70,6 +72,15 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
}
|
||||
ReadDataOp readDataOp;
|
||||
|
||||
// Keep the CLI phase between state-machine ticks. Blocking here prevents
|
||||
// the state machine from processing a UI STOP request.
|
||||
PoseidonReadPhaseRunner poseidonPhaseRunner;
|
||||
List<IPoseidonReadOperation> poseidonPhaseReaders;
|
||||
DateTime poseidonPhaseStartedAt;
|
||||
DateTime poseidonNextProgressLogAt;
|
||||
bool sendStartPhaseInitialized;
|
||||
int sendStartPhaseIterations;
|
||||
|
||||
|
||||
public EntryForm() { }
|
||||
|
||||
@ -126,6 +137,8 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
//entryFormCfg.Direction = Direction.S640;
|
||||
//currentOp = CurrentOp.EnterTestStartStates;
|
||||
this.regReaders = regReaders;
|
||||
log.InfoFormat("Poseidon data-entry requested START; operation={0}, batchWMs={1}, readers=[{2}]",
|
||||
currentOp, waterMeters == null ? -1 : waterMeters.Count, DescribeReaders(regReaders));
|
||||
int iterator = 0;
|
||||
foreach (IRegReader reader in regReaders)
|
||||
{
|
||||
@ -167,35 +180,105 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
this.refVolume = refVolume;
|
||||
this.errLimLo = errLimLo;
|
||||
this.errLimHi = errLimHi;
|
||||
log.InfoFormat("Poseidon data-entry requested END; operation={0}, batchWMs={1}, refVolume={2}, errLow={3}, errHigh={4}, readers=[{5}]",
|
||||
currentOp, waterMeters == null ? -1 : waterMeters.Count, refVolume, errLimLo, errLimHi,
|
||||
DescribeReaders(regReaders));
|
||||
return this;
|
||||
}
|
||||
|
||||
delegate void EntryFormDlgt(EntryForm myRef);
|
||||
|
||||
string DescribeReaders(IRegReader[] readers)
|
||||
{
|
||||
if (readers == null) return "<null>";
|
||||
|
||||
var descriptions = new List<string>();
|
||||
for (int index = 0; index < readers.Length; index++)
|
||||
{
|
||||
IRegReader reader = readers[index];
|
||||
if (reader == null)
|
||||
{
|
||||
descriptions.Add(index + ":<null>");
|
||||
continue;
|
||||
}
|
||||
|
||||
PoseidonReader poseidonReader = reader as PoseidonReader;
|
||||
descriptions.Add(poseidonReader == null
|
||||
? index + ":" + reader.GetType().Name
|
||||
: string.Format("{0}:{1}(COM{2},state={3})", index, poseidonReader.Name,
|
||||
poseidonReader.ComPortNr, poseidonReader.CurrentOp));
|
||||
}
|
||||
return string.Join("; ", descriptions);
|
||||
}
|
||||
|
||||
int EnabledWaterMetersCount()
|
||||
{
|
||||
if (disabled == null) return TBF.Data.WMsCount;
|
||||
int count = 0;
|
||||
for (int index = 0; index < disabled.Length; index++)
|
||||
if (!disabled[index]) count++;
|
||||
return count;
|
||||
}
|
||||
///
|
||||
void OpenBeginningDlg(EntryForm myRef)
|
||||
{
|
||||
if (ShowForm == 0)
|
||||
return;
|
||||
log.DebugFormat("Poseidon data-entry: creating CycleBeginningForm; configuredWMs={0}, batchWMs={1}",
|
||||
TBF.Data.WMsCount, waterMeters == null ? -1 : waterMeters.Count);
|
||||
myRef.modelessDlg = new CycleBeginningForm(TBF.Data.WMsCount, myRef.entryFormCfg,
|
||||
ProcessData.SelectedProcedure.OrderInfo != null ? ProcessData.SelectedProcedure.OrderInfo.POName : string.Empty);
|
||||
(myRef.modelessDlg as CycleBeginningForm)?.AutoClickOkAfterDelay();
|
||||
modelessDlg.Show();
|
||||
}
|
||||
|
||||
// The state machine runs on a worker thread. A synchronous Invoke can
|
||||
// deadlock it while the UI is waiting for the next state-machine tick.
|
||||
void BeginOpenDialog(string dialogName, EntryFormDlgt openDialog)
|
||||
{
|
||||
modelessDialogOpening = true;
|
||||
modelessDialogWaitLogged = false;
|
||||
log.InfoFormat("Poseidon data-entry: queueing dialog={0}, operation={1}, showForm={2}, readers=[{3}]",
|
||||
dialogName, currentOp, ShowForm, DescribeReaders(regReaders));
|
||||
Program.MainWnd.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
log.DebugFormat("Poseidon data-entry: opening dialog={0}, operation={1}", dialogName, currentOp);
|
||||
openDialog(this);
|
||||
log.InfoFormat("Poseidon data-entry: dialog opened={0}, operation={1}, formType={2}",
|
||||
dialogName, currentOp, modelessDlg == null ? "<null>" : modelessDlg.GetType().Name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
modelessDialogOpening = false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
///
|
||||
void OpenTestStartStatesDlg(EntryForm myRef)
|
||||
{
|
||||
if (ShowForm == 0)
|
||||
return;
|
||||
log.DebugFormat("Poseidon data-entry: creating TestStartEndForm START; configuredWMs={0}, enabledWMs={1}, batchWMs={2}, readers=[{3}]",
|
||||
TBF.Data.WMsCount, EnabledWaterMetersCount(), waterMeters == null ? -1 : waterMeters.Count, DescribeReaders(regReaders));
|
||||
myRef.modelessDlg = new TestStartEndForm(myRef.waterMeters.Count, myRef.regReaders, disabled);
|
||||
modelessDlg.Show();
|
||||
log.DebugFormat("Poseidon data-entry: TestStartEndForm START visible={0}, handleCreated={1}",
|
||||
modelessDlg.Visible, modelessDlg.IsHandleCreated);
|
||||
}
|
||||
///
|
||||
void OpenTestEndStatesDlg(EntryForm myRef)
|
||||
{
|
||||
if (ShowForm == 0)
|
||||
return;
|
||||
log.DebugFormat("Poseidon data-entry: creating TestStartEndForm END; configuredWMs={0}, enabledWMs={1}, batchWMs={2}, refVolume={3}, errLow={4}, errHigh={5}, readers=[{6}]",
|
||||
TBF.Data.WMsCount, EnabledWaterMetersCount(), waterMeters == null ? -1 : waterMeters.Count,
|
||||
refVolume, errLimLo, errLimHi, DescribeReaders(regReaders));
|
||||
myRef.modelessDlg = new TestStartEndForm(TBF.Data.WMsCount, myRef.regReaders, wmStartStateStr, disabled, refVolume, errLimLo, errLimHi);
|
||||
modelessDlg.Show();
|
||||
log.DebugFormat("Poseidon data-entry: TestStartEndForm END visible={0}, handleCreated={1}",
|
||||
modelessDlg.Visible, modelessDlg.IsHandleCreated);
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
@ -204,6 +287,12 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
readDataOp = ReadDataOp.None;
|
||||
readAndSetDataToMeters = false;
|
||||
filedDataToMeters = false;
|
||||
poseidonPhaseRunner = null;
|
||||
poseidonPhaseReaders = null;
|
||||
sendStartPhaseInitialized = false;
|
||||
sendStartPhaseIterations = 0;
|
||||
modelessDialogOpening = false;
|
||||
modelessDialogWaitLogged = false;
|
||||
|
||||
if (ShowForm == 0)
|
||||
return ;
|
||||
@ -215,7 +304,7 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
//ReadAndSetDataToMeters();
|
||||
if (ProcessData.SelectedProcedure.OrderInfo == null)
|
||||
{
|
||||
Program.MainWnd.Invoke(new EntryFormDlgt(OpenBeginningDlg), this);
|
||||
BeginOpenDialog("CycleBeginningForm", OpenBeginningDlg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -225,10 +314,10 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
}
|
||||
break;
|
||||
case CurrentOp.ReadDatastream_StartStates:
|
||||
Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestStartStatesDlg), this);
|
||||
BeginOpenDialog("TestStartEndForm.START", OpenTestStartStatesDlg);
|
||||
break;
|
||||
case CurrentOp.ReadDatastream_EndStates:
|
||||
Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestEndStatesDlg), this);
|
||||
BeginOpenDialog("TestStartEndForm.END", OpenTestEndStatesDlg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -240,6 +329,17 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
/// <returns>Event.ResultsPrinted</returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (modelessDialogOpening)
|
||||
{
|
||||
if (!modelessDialogWaitLogged)
|
||||
{
|
||||
log.WarnFormat("Poseidon data-entry: state machine waiting for dialog open; operation={0}, readers=[{1}]",
|
||||
currentOp, DescribeReaders(regReaders));
|
||||
modelessDialogWaitLogged = true;
|
||||
}
|
||||
return Event.ModelessFormIsOpen;
|
||||
}
|
||||
|
||||
if (!readAndSetDataToMeters) // run until not finished
|
||||
readAndSetDataToMeters = ReadAndSetDataToMeters();
|
||||
|
||||
@ -352,7 +452,8 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
}
|
||||
}
|
||||
resultSaved = true;
|
||||
modelessDlg = null;
|
||||
modelessDlg = null;
|
||||
modelessDialogOpening = false;
|
||||
}
|
||||
|
||||
return Event.ModelessFormClosed; /// Form closed
|
||||
@ -369,6 +470,7 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
currentOp = CurrentOp.None;
|
||||
readAndSetDataToMeters = false;
|
||||
filedDataToMeters = false;
|
||||
sendStartPhaseInitialized = false;
|
||||
}
|
||||
|
||||
public int ShowForm
|
||||
@ -389,93 +491,108 @@ namespace TBF.Rig.DataEntry.PoseidonCmd
|
||||
bool bOperationSuccess = false;
|
||||
if (currentOp == CurrentOp.SendStartDataStream)
|
||||
{
|
||||
bool finishedReading = regReaders == null; // we can work only with register readers
|
||||
while (!finishedReading) //TODO BUMI lock - fuck ?
|
||||
if (!sendStartPhaseInitialized)
|
||||
{
|
||||
bool bAllReadersFinished = true;
|
||||
foreach (var iRegReader in regReaders )
|
||||
sendStartPhaseInitialized = true;
|
||||
sendStartPhaseIterations = 0;
|
||||
poseidonPhaseStartedAt = DateTime.UtcNow;
|
||||
poseidonNextProgressLogAt = poseidonPhaseStartedAt.AddSeconds(5);
|
||||
log.InfoFormat("Poseidon send-start phase started; readers=[{0}]", DescribeReaders(regReaders));
|
||||
if (regReaders != null)
|
||||
{
|
||||
if (iRegReader is PoseidonReader)
|
||||
foreach (IRegReader regReader in regReaders)
|
||||
{
|
||||
PoseidonReader poseidonReader = (iRegReader as PoseidonReader);
|
||||
PoseidonReader poseidonReader = regReader as PoseidonReader;
|
||||
if (poseidonReader == null) continue;
|
||||
poseidonReader.SetCliLogging(CliLogging);
|
||||
|
||||
if (poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.SendStartDataStream_Done
|
||||
|| poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.SendStartDataStream_Runing)
|
||||
{
|
||||
poseidonReader.SetCurrentOp(PoseidonReader.CurrentPoseidonOp.SendStartDataStream);
|
||||
}
|
||||
/// Send start data stream
|
||||
poseidonReader.Run();
|
||||
readDataOp = ReadDataOp.Start;
|
||||
if (!(poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Done
|
||||
|| poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Error))
|
||||
{
|
||||
bAllReadersFinished = false;
|
||||
}
|
||||
poseidonReader.SetCurrentOp(PoseidonReader.CurrentPoseidonOp.SendStartDataStream);
|
||||
log.DebugFormat("Poseidon send-start: armed reader={0}, COM={1}, state={2}",
|
||||
poseidonReader.Name, poseidonReader.ComPortNr, poseidonReader.CurrentOp);
|
||||
}
|
||||
}
|
||||
/// Wait for all readers to finish
|
||||
if (bAllReadersFinished)
|
||||
{
|
||||
finishedReading = true;
|
||||
readDataOp = ReadDataOp.Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
bOperationSuccess = true;
|
||||
sendStartPhaseIterations++;
|
||||
bool allReadersFinished = true;
|
||||
if (regReaders != null)
|
||||
{
|
||||
foreach (IRegReader regReader in regReaders)
|
||||
{
|
||||
PoseidonReader poseidonReader = regReader as PoseidonReader;
|
||||
if (poseidonReader == null) continue;
|
||||
poseidonReader.Run();
|
||||
readDataOp = ReadDataOp.Start;
|
||||
if (poseidonReader.CurrentOp != PoseidonReader.CurrentPoseidonOp.Done
|
||||
&& poseidonReader.CurrentOp != PoseidonReader.CurrentPoseidonOp.Error)
|
||||
allReadersFinished = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (allReadersFinished)
|
||||
{
|
||||
readDataOp = ReadDataOp.Done;
|
||||
log.InfoFormat("Poseidon send-start phase completed; iterations={0}, elapsedMs={1}",
|
||||
sendStartPhaseIterations, (long)(DateTime.UtcNow - poseidonPhaseStartedAt).TotalMilliseconds);
|
||||
sendStartPhaseInitialized = false;
|
||||
bOperationSuccess = true;
|
||||
}
|
||||
else if (DateTime.UtcNow >= poseidonNextProgressLogAt)
|
||||
{
|
||||
log.WarnFormat("Poseidon send-start phase waiting; iterations={0}, elapsedMs={1}, readers=[{2}]",
|
||||
sendStartPhaseIterations, (long)(DateTime.UtcNow - poseidonPhaseStartedAt).TotalMilliseconds,
|
||||
DescribeReaders(regReaders));
|
||||
poseidonNextProgressLogAt = DateTime.UtcNow.AddSeconds(5);
|
||||
}
|
||||
}
|
||||
else if ((currentOp == CurrentOp.ReadDatastream_StartStates)
|
||||
|| (currentOp == CurrentOp.ReadDatastream_EndStates))
|
||||
{
|
||||
bool finishedReading = regReaders == null; // we can work only with register readers
|
||||
while (!finishedReading) //TODO BUMI lock - fuck ?
|
||||
if (poseidonPhaseRunner == null)
|
||||
{
|
||||
bool bAllReadersFinished = true;
|
||||
foreach (var iRegReader in regReaders )
|
||||
poseidonPhaseReaders = new List<IPoseidonReadOperation>();
|
||||
if (regReaders != null)
|
||||
{
|
||||
if (iRegReader is PoseidonReader)
|
||||
foreach (IRegReader regReader in regReaders)
|
||||
{
|
||||
PoseidonReader poseidonReader = (iRegReader as PoseidonReader);
|
||||
if(poseidonReader == null)
|
||||
continue;
|
||||
PoseidonReader poseidonReader = regReader as PoseidonReader;
|
||||
if (poseidonReader == null) continue;
|
||||
poseidonReader.SetCliLogging(CliLogging);
|
||||
// A terminal reader must not be armed again. Re-starting Error/Done
|
||||
// launched the CLI on every polling iteration and kept the dialog loading.
|
||||
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);
|
||||
if (!(poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Done
|
||||
|| poseidonReader.CurrentOp == PoseidonReader.CurrentPoseidonOp.Error))
|
||||
{
|
||||
bAllReadersFinished = false;
|
||||
}
|
||||
poseidonPhaseReaders.Add(new PoseidonReaderOperation(poseidonReader));
|
||||
}
|
||||
}
|
||||
if (bAllReadersFinished)
|
||||
{
|
||||
log.DebugFormat("Poseidon read: all readers finished for {0}", currentOp);
|
||||
finishedReading = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
poseidonPhaseRunner = new PoseidonReadPhaseRunner(
|
||||
currentOp == CurrentOp.ReadDatastream_StartStates);
|
||||
poseidonPhaseStartedAt = DateTime.UtcNow;
|
||||
poseidonNextProgressLogAt = poseidonPhaseStartedAt.AddSeconds(5);
|
||||
log.InfoFormat("Poseidon phase started: phase={0}, readers={1}, detail=[{2}]",
|
||||
currentOp, poseidonPhaseReaders.Count, DescribeReaders(regReaders));
|
||||
}
|
||||
|
||||
bOperationSuccess = true;
|
||||
bool allReadersFinished = poseidonPhaseRunner.RunIteration(poseidonPhaseReaders);
|
||||
foreach (IPoseidonReadOperation poseidonReader in poseidonPhaseReaders)
|
||||
if (poseidonReader.HasError)
|
||||
log.ErrorFormat("Poseidon read: {0} completed with Error during {1}", poseidonReader.Name, currentOp);
|
||||
|
||||
if (allReadersFinished)
|
||||
{
|
||||
log.InfoFormat("Poseidon phase completed: phase={0}, iterations={1}, elapsedMs={2}",
|
||||
currentOp, poseidonPhaseRunner.IterationCount,
|
||||
(long)(DateTime.UtcNow - poseidonPhaseStartedAt).TotalMilliseconds);
|
||||
poseidonPhaseRunner = null;
|
||||
poseidonPhaseReaders = null;
|
||||
bOperationSuccess = true;
|
||||
}
|
||||
else if (DateTime.UtcNow >= poseidonNextProgressLogAt)
|
||||
{
|
||||
var pendingReaders = new List<string>();
|
||||
foreach (IPoseidonReadOperation poseidonReader in poseidonPhaseReaders)
|
||||
if (!poseidonReader.IsFinished) pendingReaders.Add(poseidonReader.Name);
|
||||
log.WarnFormat("Poseidon phase waiting: phase={0}, iterations={1}, elapsedMs={2}, pending={3}",
|
||||
currentOp, poseidonPhaseRunner.IterationCount,
|
||||
(long)(DateTime.UtcNow - poseidonPhaseStartedAt).TotalMilliseconds,
|
||||
string.Join(",", pendingReaders));
|
||||
poseidonNextProgressLogAt = DateTime.UtcNow.AddSeconds(5);
|
||||
}
|
||||
}
|
||||
|
||||
return bOperationSuccess;
|
||||
|
||||
@ -300,6 +300,7 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
|
||||
public void AddRunAndCaptureJsonAsync<T>(string fileName, string args) where T : new()
|
||||
{
|
||||
log?.Debug($"CLI queued: file='{fileName}', args='{args}'");
|
||||
ResetStartTime();
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
@ -334,6 +335,7 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
|
||||
try
|
||||
{
|
||||
log?.Debug($"CLI starting: file='{psi.FileName}', args='{psi.Arguments}', workingDirectory='{psi.WorkingDirectory}', exists={System.IO.File.Exists(psi.FileName)}");
|
||||
process.Start();
|
||||
|
||||
var stdoutTask = process.StandardOutput.ReadToEndAsync();
|
||||
@ -363,6 +365,7 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
info.StandardError = stderrTask.Result ?? "";
|
||||
string allOutput = info.StandardOutput + info.StandardError;
|
||||
log?.Debug(allOutput);
|
||||
log?.Debug($"CLI completed: name='{info.Name}', exitCode={info.ExitCode}, stdoutLength={info.StandardOutput.Length}, stderrLength={info.StandardError.Length}");
|
||||
|
||||
if (info.ExitCode != 0)
|
||||
{
|
||||
|
||||
@ -46,4 +46,39 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
return allReadersFinished;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Owns one dialog phase (START or STOP). A reader is armed once per phase,
|
||||
/// independently of its terminal state from a preceding phase.
|
||||
/// </summary>
|
||||
public sealed class PoseidonReadPhaseRunner
|
||||
{
|
||||
private readonly bool readStart;
|
||||
private readonly HashSet<IPoseidonReadOperation> startedReaders =
|
||||
new HashSet<IPoseidonReadOperation>();
|
||||
|
||||
public int IterationCount { get; private set; }
|
||||
|
||||
public PoseidonReadPhaseRunner(bool readStart)
|
||||
{
|
||||
this.readStart = readStart;
|
||||
}
|
||||
|
||||
public bool RunIteration(IEnumerable<IPoseidonReadOperation> readers)
|
||||
{
|
||||
if (readers == null) return true;
|
||||
|
||||
IterationCount++;
|
||||
|
||||
bool allReadersFinished = true;
|
||||
foreach (IPoseidonReadOperation reader in readers)
|
||||
{
|
||||
if (reader == null) continue;
|
||||
if (startedReaders.Add(reader)) reader.Start(readStart);
|
||||
reader.Run();
|
||||
if (!reader.IsFinished) allReadersFinished = false;
|
||||
}
|
||||
return allReadersFinished;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,9 +294,17 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
if ((DebugLevel == DebugMode.Normal)||(DebugLevel == DebugMode.Simulate))
|
||||
{
|
||||
/// Prepare serial port
|
||||
serialPort = new SerialPortData(string.Format("COM{0}", registerReaderCfg.ComPortNr),
|
||||
registerReaderCfg.CliFileName,
|
||||
registerReaderCfg.MeterType);
|
||||
if (registerReaderCfg.MeterType <= 0)
|
||||
{
|
||||
log.WarnFormat(
|
||||
"{0}: configured Poseidon MeterType={1}; using CLI default MeterType={2}.",
|
||||
Name,
|
||||
registerReaderCfg.MeterType,
|
||||
SerialPortData.DefaultPoseidonMeterType);
|
||||
}
|
||||
serialPort = new SerialPortData(string.Format("COM{0}", registerReaderCfg.ComPortNr),
|
||||
registerReaderCfg.CliFileName,
|
||||
registerReaderCfg.MeterType);
|
||||
|
||||
|
||||
//TODO BUMI prepare serial port - for us do nothing
|
||||
@ -438,6 +446,8 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
{
|
||||
_currentOp = CurrentPoseidonOp.ReadDatastream_Done;
|
||||
incommingTime = CliRunner.IncommingTime;
|
||||
log.DebugFormat("{0}: CLI task completed for {1}; incomingTime={2}", Name,
|
||||
_isReadingStart ? "START" : "STOP", incommingTime);
|
||||
}
|
||||
else if (CliRunner.TimeOutReceived(SafetyTimeOut))
|
||||
{
|
||||
@ -445,6 +455,8 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
CliRunner.CancelUndoneTasksAsTimedOut();
|
||||
_currentOp = CurrentPoseidonOp.ReadDatastream_Done;
|
||||
incommingTime = CliRunner.IncommingTime;
|
||||
log.ErrorFormat("{0}: CLI timeout for {1}; timeoutMs={2}", Name,
|
||||
_isReadingStart ? "START" : "STOP", SafetyTimeOut);
|
||||
}
|
||||
|
||||
return Event.Busy;
|
||||
@ -468,6 +480,11 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
}
|
||||
else
|
||||
{
|
||||
lastCliReadFailureReason = _lastOpTimedOut
|
||||
? "CLI read timed out."
|
||||
: "No completed JsonDataFromPoseidon task was available.";
|
||||
log.ErrorFormat("{0}: Poseidon {1} read failed: {2}", Name,
|
||||
_isReadingStart ? "START" : "STOP", lastCliReadFailureReason);
|
||||
if (_lastOpTimedOut)
|
||||
{
|
||||
log.Warn($"PoseidonReader {Name}: ReadDatastream timed out, no completed result available.");
|
||||
|
||||
@ -6,6 +6,9 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
public class SerialPortData
|
||||
{
|
||||
public const string CliDirectory = @"C:\TBF\Cli";
|
||||
// HatCliDemo identifies Poseidon with the numeric meter type 74.
|
||||
// Older persisted configurations can contain the uninitialized value 0.
|
||||
public const int DefaultPoseidonMeterType = 74;
|
||||
|
||||
private Boolean? _cliExists;
|
||||
public bool CliExists { get {
|
||||
@ -30,6 +33,11 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
public string PortName { get; set; }
|
||||
public int MeterType { get; set; }
|
||||
|
||||
public static int NormalizeMeterType(int meterType)
|
||||
{
|
||||
return meterType > 0 ? meterType : DefaultPoseidonMeterType;
|
||||
}
|
||||
|
||||
public enum EMeterArg {
|
||||
Calibration = 0,
|
||||
AllParams = 2,
|
||||
@ -59,7 +67,7 @@ namespace TBF.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
{
|
||||
PortName = portName;
|
||||
CmdClientName = cmdClientName;
|
||||
MeterType = meterType;
|
||||
MeterType = NormalizeMeterType(meterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,6 +246,17 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SerialPortData_ZeroMeterType_UsesPoseidonCliDefault()
|
||||
{
|
||||
var serialPort = new SerialPortData("COM3", "HatCliDemo.exe", 0);
|
||||
|
||||
Assert.AreEqual(SerialPortData.DefaultPoseidonMeterType, serialPort.MeterType);
|
||||
Assert.AreEqual(
|
||||
"-p COM3 -m 74 --operation readall",
|
||||
serialPort.DefaultArgSettings(SerialPortData.EMeterArg.AllParams));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CliProcess_ExitErrorWithoutJson_RecordsDiagnosticsAndReturnsNoReading()
|
||||
{
|
||||
|
||||
@ -50,6 +50,27 @@ namespace TBFTests.Rig.RegisterReaders.PoseidonCmdStartStop
|
||||
foreach (FakeReader reader in readers) Assert.AreEqual(1, reader.StartCount, reader.Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StartThenStop_PhasesArmTheSameReaderOncePerPhase()
|
||||
{
|
||||
var reader = new FakeReader("Pos1", 1);
|
||||
var readers = new List<IPoseidonReadOperation> { reader };
|
||||
var startPhase = new PoseidonReadPhaseRunner(true);
|
||||
|
||||
// START phase completes.
|
||||
startPhase.RunIteration(readers);
|
||||
startPhase.RunIteration(readers);
|
||||
Assert.AreEqual(CmdPoseidonReader.CurrentPoseidonOp.Done, reader.CurrentOp);
|
||||
|
||||
// A new STOP phase re-arms the terminal reader exactly once.
|
||||
var stopPhase = new PoseidonReadPhaseRunner(false);
|
||||
stopPhase.RunIteration(readers);
|
||||
stopPhase.RunIteration(readers);
|
||||
|
||||
Assert.AreEqual(2, reader.StartCount);
|
||||
Assert.AreEqual(CmdPoseidonReader.CurrentPoseidonOp.Done, reader.CurrentOp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InputJson_ZeroReading_WithDecimalCommaOrDot_IsValid()
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user