tbf/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs
Michal Buzik b0083afa10 DataEntry.UNI - timeout, autoclose improve
Introduce configurable timeouts for data entry volume reads in `IRegReaderSmart` and its implementations: added optional timeout parameters and updated default values across associated forms and methods. Updated `EntryFormCfg` to support customizable timeout settings.
2026-08-19 23:47:50 +02:00

507 lines
21 KiB
C#

///
/// Copyright (c) 2023 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using Common;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.DataEntry.Uni
{
public class EntryFormNoStartEnd : ComponentBase, IOperation, IDataEntry, IHasCycleBeginForm, IHasCycleEndForm
{
private static readonly ILog log = LogManager.GetLogger(typeof(EntryFormNoStartEnd));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
const string DfltOcrWorkspaceFolder = "C:\\TBF\\OCR\\";
const string DfltOcrWorkspaceExt = ".vrws";
static Dictionary<string, OcrVidi> ocrDictionary = new Dictionary<string, OcrVidi>();
readonly EntryFormCfg myCfg;
public string OcrWorkspace
{
get { return (myCfg != null && myCfg.ProcParams != null) ? myCfg.ProcParams.OcrWorkspace : string.Empty; }
}
public string OcrStream
{
get { return (myCfg != null && myCfg.ProcParams != null) ? myCfg.ProcParams.OcrStream : string.Empty; }
}
IRegReader[] regReaders;
public string[] StartImages
{
get { return startImages; }
set
{
if (myCfg.DebugLevel == DebugMode.Simulate)
{
startImages = new string[] { "C:\\TBF\\Images\\Test\\Image1.bmp", "C:\\TBF\\Images\\Test\\Image2.bmp",
"C:\\TBF\\Images\\Test\\Image3.bmp", "C:\\TBF\\Images\\Test\\Image4.bmp", "C:\\TBF\\Images\\Test\\Image5.bmp",
"C:\\TBF\\Images\\Test\\Image1.bmp", "C:\\TBF\\Images\\Test\\Image2.bmp", "C:\\TBF\\Images\\Test\\Image3.bmp",
"C:\\TBF\\Images\\Test\\Image4.bmp", "C:\\TBF\\Images\\Test\\Image5.bmp", "C:\\TBF\\Images\\Test\\Image1.bmp",
"C:\\TBF\\Images\\Test\\Image2.bmp", "C:\\TBF\\Images\\Test\\Image3.bmp", "C:\\TBF\\Images\\Test\\Image4.bmp",
"C:\\TBF\\Images\\Test\\Image5.bmp", "C:\\TBF\\Images\\Test\\Image1.bmp", "C:\\TBF\\Images\\Test\\Image2.bmp",
"C:\\TBF\\Images\\Test\\Image3.bmp", "C:\\TBF\\Images\\Test\\Image4.bmp", "C:\\TBF\\Images\\Test\\Image5.bmp" };
}
else
{
startImages = value;
}
}
}
string[] startImages;
public string[] EndImages
{
get { return endImages; }
set { endImages = value; }
}
string[] endImages;
public bool SaveImages
{
get
{
return !string.IsNullOrEmpty(myCfg.TestStartPicName) || !string.IsNullOrEmpty(myCfg.TestEndPicName); // or return myCfg.SaveImages;
}
}
string[] wmCycleEndState;
public string WMCycleEndState(int wmNr) { return (wmNr >= 0 && wmNr < wmCycleEndState.Length) ? wmCycleEndState[wmNr] : string.Empty; }
double[] wmStartState;
public double WMStartState(int wmNr) { return (wmNr >= 0 && wmNr < wmStartState.Length) ? wmStartState[wmNr] : 0; }
double[] wmEndState;
public double WMEndState(int wmNr) { return (wmNr >= 0 && wmNr < wmEndState.Length) ? wmEndState[wmNr] : 0; }
string[] wmStartStateStr;
System.Windows.Forms.Form modelessDlg;
public bool Completed { get { return (modelessDlg is IHasCompleted) ? (modelessDlg as IHasCompleted).Completed : true; } }
Unit volumeUnit;
double refVolume;
double errLimLo;
double errLimHi;
bool resultSaved; /// Set in Run() when results are saved
IList<Results.Entities.WaterMeter> waterMeters; /// Reference to ...ProcessData.BatchRslts.WaterMeters[]
public string TestStartImgName(int wmNr0, string testName)
{
if (myCfg == null || waterMeters == null || wmNr0 < 0 || wmNr0 >= waterMeters.Count) return string.Empty;
var wm = waterMeters[wmNr0];
/// {0} {1} {2} {3} {4} {5} {6} {7} {8} {9}
return string.Format(myCfg.TestStartPicName, testName, wm.SerialNr, wm.SerialNrAux, wm.RadioAddress, wm.Remark, wm.ArchivePath, wm.YearOfProduction, wm.Batch.StartTime, wm.Batch.BatchNr, wm.WMPosition);
}
public string TestEndImgName(int wmNr0, string testName)
{
if (myCfg == null || waterMeters == null || wmNr0 < 0 || wmNr0 >= waterMeters.Count) return string.Empty;
var wm = waterMeters[wmNr0];
/// {0} {1} {2} {3} {4} {5} {6} {7} {8} {9}
return string.Format(myCfg.TestEndPicName, testName, wm.SerialNr, wm.SerialNrAux, wm.RadioAddress, wm.Remark, wm.ArchivePath, wm.YearOfProduction, wm.Batch.StartTime, wm.Batch.BatchNr, wm.WMPosition);
}
public enum CurrentOp
{
None,
FormAtCycleBeginning,
FormAtCycleEnd,
TestStartStates,
TestEndStates,
DeferredTestEval,
}
CurrentOp currentOp;
public EntryFormNoStartEnd() { }
public EntryFormNoStartEnd(Generic.IComponentCfg cfg)
: base(cfg)
{
myCfg = cfg as EntryFormCfg;
}
public override void Initialize()
{
wmStartState = new double[TBF.Data.WMsCount];
wmStartStateStr = new string[TBF.Data.WMsCount];
wmEndState = new double[TBF.Data.WMsCount];
wmCycleEndState = new string[TBF.Data.WMsCount];
volumeUnit = (Sequences.ProcessData.BenchInfo != null && Sequences.ProcessData.BenchInfo.VolumeUnit != Unit.None)
? Sequences.ProcessData.BenchInfo.VolumeUnit : Unit.l;
currentOp = CurrentOp.None;
log.FatalFormat("{0} initialized: {1}", Name, this);
}
/// <returns>Reference to the operation</returns>
public IOperation ShowCycleBeginFormOp( IRegReader[] regReadersOptional = null)
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.FormAtCycleBeginning;
this.waterMeters = Sequences.ProcessData.BatchRslts.Batch.WaterMeters;
this.regReaders = regReadersOptional;
log.DebugFormat(
"DATA_ENTRY_BEGIN_ASSIGN OptionalSlots={0}, OptionalReaders={1}, StoredSlots={2}, StoredReaders={3}",
regReadersOptional == null ? 0 : regReadersOptional.Length,
regReadersOptional == null ? 0 : Array.FindAll(regReadersOptional, reader => reader != null).Length,
this.regReaders == null ? 0 : this.regReaders.Length,
this.regReaders == null ? 0 : Array.FindAll(this.regReaders, reader => reader != null).Length);
return this;
}
/// <returns>Reference to the operation</returns>
public IOperation ShowCycleEndFormOp(IList<Results.Entities.WaterMeter> waterMeters)
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.FormAtCycleEnd;
this.waterMeters = waterMeters;
return this;
}
/// <returns>Reference to the operation</returns>
public IOperation ShowTestStartFormOp(IRegReader[] regReaders)
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.TestStartStates;
this.waterMeters = Sequences.ProcessData.BatchRslts.Batch.WaterMeters;
this.regReaders = regReaders;
return this;
}
/// <returns>Reference to the operation</returns>
public IOperation ShowTestEndFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi)
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.TestEndStates;
this.waterMeters = Sequences.ProcessData.BatchRslts.Batch.WaterMeters;
this.regReaders = regReaders;
this.refVolume = refVolume;
this.errLimLo = errLimLo;
this.errLimHi = errLimHi;
return this;
}
/// <returns>null (not implemented)</returns>
public IOperation ShowAdvancedTestStartFormOp(IRegReader[] regReaders, IList<Results.Entities.WaterMeter> waterMeters, bool isCondOp = false)
{
return null;
}
public IOperation ShowTestCollectFormOp(IRegReader[] regReaders, double volumeRef, double errLimLo, double errLimHi) { return null; }
/// <returns>Reference to the operation</returns>
public IOperation ShowDeferredTestEvalFormOp(IRegReader[] regReaders, double refVolume, double errLimLo, double errLimHi)
{
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.DeferredTestEval;
this.waterMeters = Sequences.ProcessData.BatchRslts.Batch.WaterMeters;
this.regReaders = regReaders;
this.refVolume = refVolume;
this.errLimLo = errLimLo;
this.errLimHi = errLimHi;
return this;
}
delegate void EntryFormDlgt(EntryFormNoStartEnd myRef);
///
void OpenBeginningDlg(EntryFormNoStartEnd myRef)
{
string ocrMessage;
var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage);
DEItem.ClearItems();
for (int i = 0; i < myCfg.GetBgItemsCount(); i++)
{
if (myCfg.BgItemContent[i] != Ct.None)
{
DEItem.AddItem(myCfg.BgItemContent[i], myCfg.BgItemCaption[i], myCfg.BgItemAction[i], myCfg.BgItemWidth[i]);
}
}
DEItem.ClearColumns();
for (int i = 0; i < myCfg.GetBgColumnsCount(); i++)
{
if (myCfg.BgColumnContent[i] != Ct.None)
{
DEItem.AddColumn(myCfg.BgColumnContent[i], myCfg.BgColumnCaption[i], myCfg.BgColumnAction[i], myCfg.BgColumnWidth[i]);
}
}
log.DebugFormat(
"DATA_ENTRY_BEGIN_OPEN AutoRead={0}, StoredSlots={1}, StoredReaders={2}, " +
"WaterMeters={3}, OptoHeadsEnabled=0x{4:X12}",
myCfg.BgIsAutoReadingSerialNo,
regReaders == null ? 0 : regReaders.Length,
regReaders == null ? 0 : Array.FindAll(regReaders, reader => reader != null).Length,
waterMeters == null ? 0 : waterMeters.Count,
Program.LocalSettings.OptoHeadsEnabled);
if (regReaders != null)
{
modelessDlg = new CycleBgEnForm(waterMeters, regReaders, TBF.Data.LineSize, myCfg.BgTitle, myCfg.BgSize, myCfg.BgIsLrOrder, myCfg.BgIsCameraPicture,
myCfg.BgFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), false, regReaders, myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap);
}
else
{
modelessDlg = new CycleBgEnForm(waterMeters, TBF.Data.LineSize, myCfg.BgTitle, myCfg.BgSize, myCfg.BgIsLrOrder, myCfg.BgIsCameraPicture,
myCfg.BgFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap, false);
}
modelessDlg.Show();
}
///
void OpenEndDlg(EntryFormNoStartEnd myRef)
{
string ocrMessage;
var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage);
DEItem.ClearItems();
for (int i = 0; i < myCfg.GetEnItemsCount(); i++)
{
if (myCfg.EnItemContent[i] != Ct.None)
{
DEItem.AddItem(myCfg.EnItemContent[i], myCfg.EnItemCaption[i], myCfg.EnItemAction[i], myCfg.EnItemWidth[i]);
}
}
DEItem.ClearColumns();
for (int i = 0; i < myCfg.GetEnColumnsCount(); i++)
{
if (myCfg.EnColumnContent[i] != Ct.None)
{
DEItem.AddColumn(myCfg.EnColumnContent[i], myCfg.EnColumnCaption[i], myCfg.EnColumnAction[i], myCfg.EnColumnWidth[i]);
}
}
modelessDlg = new CycleBgEnForm(waterMeters, TBF.Data.LineSize, myCfg.EnTitle, myCfg.EnSize, myCfg.EnIsLrOrder, myCfg.EnIsCameraPicture,
myCfg.EnFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap, true);
modelessDlg.Show();
}
///
void OpenTestStartStatesDlg(EntryFormNoStartEnd myRef)
{
string ocrMessage;
var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage);
DEItem.ClearColumns();
for (int i = 0; i < myCfg.GetTestColumnsCount(); i++)
{
if (myCfg.TestColumnContent[i] != Ct.None)
{
DEItem.AddColumn(myCfg.TestColumnContent[i], myCfg.TestColumnCaption[i], myCfg.TestColumnAction[i], myCfg.TestColumnWidth[i]);
}
}
bool isCompound = waterMeters[0].Batch.Compound;
modelessDlg = new TestStartEndForm(waterMeters, myRef.regReaders, TBF.Data.LineSize, myCfg.TestTitle, myCfg.TestSize,
myCfg.TestStartBoxAlwaysEn, myCfg.TestIsLrOrder, myCfg.TestFormCloseKeys,
DEItem.GetColumns(), isCompound, volumeUnit, myCfg.TestIsCameraPicture,
startImages,endImages, ocr, ocrMessage, myRef.OcrStream,
myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap, myCfg.DataEntryReadTimeoutSec);
modelessDlg.Show();
}
///
void OpenTestEndStatesDlg(EntryFormNoStartEnd myRef)
{
string ocrMessage;
var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage);
DEItem.ClearColumns();
for (int i = 0; i < myCfg.GetTestColumnsCount(); i++)
{
if (myCfg.TestColumnContent[i] != Ct.None)
{
DEItem.AddColumn(myCfg.TestColumnContent[i], myCfg.TestColumnCaption[i], myCfg.TestColumnAction[i], myCfg.TestColumnWidth[i]);
}
}
bool isCompound = waterMeters[0].Batch.Compound;
modelessDlg = new TestStartEndForm(waterMeters, myRef.regReaders, TBF.Data.LineSize, myCfg.TestTitle, myCfg.TestSize,
myCfg.TestStartBoxAlwaysEn, myCfg.TestIsLrOrder, myCfg.TestFormCloseKeys, DEItem.GetColumns(),
isCompound, volumeUnit, myCfg.TestIsCameraPicture, startImages, endImages,
ocr, ocrMessage, myRef.OcrStream, myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap,
myCfg.DataEntryReadTimeoutSec, wmStartStateStr, refVolume, errLimLo, errLimHi);
modelessDlg.Show();
}
///
void OpenDeferredTestEvalDlg(EntryFormNoStartEnd myRef)
{
string ocrMessage;
var ocr = GetOcr(myRef.OcrWorkspace, out ocrMessage);
DEItem.ClearColumns();
for (int i = 0; i < myCfg.GetTestColumnsCount(); i++)
{
if (myCfg.TestColumnContent[i] != Ct.None)
{
DEItem.AddColumn(myCfg.TestColumnContent[i], myCfg.TestColumnCaption[i], myCfg.TestColumnAction[i], myCfg.TestColumnWidth[i]);
}
}
bool isCompound = waterMeters[0].Batch.Compound;
modelessDlg = new TestStartEndForm(waterMeters, myRef.regReaders, TBF.Data.LineSize, myCfg.TestTitle, myCfg.TestSize,
myCfg.TestStartBoxAlwaysEn, myCfg.TestIsLrOrder, myCfg.TestFormCloseKeys, DEItem.GetColumns(),
isCompound, volumeUnit, myCfg.TestIsCameraPicture, startImages, endImages,
ocr, ocrMessage, myRef.OcrStream, myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap,
myCfg.DataEntryReadTimeoutSec, wmStartStateStr, refVolume, errLimLo, errLimHi);
modelessDlg.Show();
}
///
OcrVidi GetOcr(string ocrWorkspace, out string message)
{
message = string.Empty;
if (string.IsNullOrEmpty(ocrWorkspace)) return null; /// No OCR was configured
string fullPath = (ocrWorkspace.Contains("\\") || ocrWorkspace.Contains("/"))
? ocrWorkspace.Replace('/', '\\')
: System.IO.Path.Combine(DfltOcrWorkspaceFolder, ocrWorkspace);
if (!fullPath.Contains(".")) fullPath = fullPath + DfltOcrWorkspaceExt;
OcrVidi ocrVidi;
if (ocrDictionary.TryGetValue(fullPath, out ocrVidi))
{
log.InfoFormat("existing OcrVidi({0}) was retrieved from dictionary", fullPath);
return ocrVidi;
}
try
{
ocrVidi = new OcrVidi(fullPath);
ocrDictionary.Add(fullPath, ocrVidi);
log.WarnFormat("new OcrVidi({0}) was added to dictionary", fullPath);
return ocrVidi;
}
catch (Exception e)
{
if (e.InnerException != null)
{
log.ErrorFormat("new OcrVidi({0}) thrown {1}: {2} / {3}",
fullPath, e.GetType().ToString(), e.Message, e.InnerException.Message);
}
else
{
log.ErrorFormat("new OcrVidi({0}) thrown {1}: {2}",
fullPath, e.GetType().ToString(), e.Message);
}
log.ErrorFormat("Stack trace:\r\n{0}", e.StackTrace);
message = string.Format("Cannot load OCR workspace:\r\n{0}\r\nOCR workspace file is {1}", e.Message, fullPath);
return null;
}
}
/// <summary>Start this operation</summary>
public void Start()
{
resultSaved = false;
switch (currentOp)
{
case CurrentOp.FormAtCycleBeginning:
if (myCfg.BgShowForm)
{
Program.MainWnd.Invoke(new EntryFormDlgt(OpenBeginningDlg), this);
}
break;
case CurrentOp.FormAtCycleEnd:
if (myCfg.EnShowForm)
{
Program.MainWnd.Invoke(new EntryFormDlgt(OpenEndDlg), this);
}
break;
case CurrentOp.TestStartStates:
if (myCfg.TestStartEndShowForm)
{
Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestStartStatesDlg), this);
}
break;
case CurrentOp.TestEndStates:
if (myCfg.TestStartEndShowForm)
{
Program.MainWnd.Invoke(new EntryFormDlgt(OpenTestEndStatesDlg), this);
}
break;
case CurrentOp.DeferredTestEval:
Program.MainWnd.Invoke(new EntryFormDlgt(OpenDeferredTestEvalDlg), this);
break;
}
}
/// <summary>Run this operation</summary>
/// <returns>Event.ResultsPrinted</returns>
public Event Run()
{
if ((modelessDlg is IHasCompleted) && !(modelessDlg as IHasCompleted).Completed)
{
return Event.ModelessFormIsOpen;
}
if (!resultSaved) /// This is to save the result only once
{
if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestStartStates)
{
/// Fixed start test - start
TestStartEndForm dlg = (modelessDlg as TestStartEndForm);
if (dlg != null)
{
volumeUnit = dlg.VolumeUnit;
for (int i = 0; i < waterMeters.Count; i++)
{
if (!((i < waterMeters.Count && waterMeters[i].Disabled) || (i < regReaders.Length && regReaders[i] == null)))
{
wmStartState[i] = dlg.WMStartState[i];
}
}
wmStartStateStr = dlg.WMStartStateStr;
}
}
else if (modelessDlg is TestStartEndForm && currentOp == CurrentOp.TestEndStates)
{
/// Fixed start test - end
TestStartEndForm dlg = (modelessDlg as TestStartEndForm);
if (dlg != null)
{
volumeUnit = dlg.VolumeUnit;
for (int i = 0; i < waterMeters.Count; i++)
{
if (!((i < waterMeters.Count && waterMeters[i].Disabled) || (i < regReaders.Length && regReaders[i] == null)))
{
wmEndState[i] = dlg.WMEndState[i];
}
}
}
}
resultSaved = true;
modelessDlg = null;
}
return Event.ModelessFormClosed; /// Form closed
}
/// <summary>Stop this operation</summary>
public void Stop()
{
if (modelessDlg is IHasCompleted)
{
UiBridge.Bridge.OnCloseModelessForm(this, null);
modelessDlg = null;
}
currentOp = CurrentOp.None;
}
}
}