FIX UNI Data Entry - corrensponded with iPerlCommunicationForm.cs

Add debug logging and UI enhancements for data entry processes: Improve register reader handling in sequences and forms, add detailed data entry debug logs, integrate serial number and volume watermarking, and update localized strings in multiple languages.
This commit is contained in:
Michal Buzik 2026-08-19 13:18:34 +02:00
parent 5803f06bdb
commit 6c3c6cd0ef
19 changed files with 396 additions and 38 deletions

View File

@ -7190,5 +7190,32 @@ namespace TBF.Resources {
return ResourceManager.GetString("Zeroing_chdr", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Loading.
/// </summary>
internal static string Loading {
get {
return ResourceManager.GetString("Loading", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Simulated.
/// </summary>
internal static string Simulated {
get {
return ResourceManager.GetString("Simulated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not loaded.
/// </summary>
internal static string Not_loaded {
get {
return ResourceManager.GetString("Not_loaded", resourceCulture);
}
}
}
}

View File

@ -1767,4 +1767,7 @@
<data name="Reload" xml:space="preserve">
<value>Znovu otevřít</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Načítání</value></data>
<data name="Simulated" xml:space="preserve"><value>Simulace</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Nenačteno</value></data>
</root>

View File

@ -2229,4 +2229,7 @@
<data name="Opto_head_was_disabled_by_the_user" xml:space="preserve">
<value>Abtastkopf wurde deaktiviert vom Benutzer!</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Laden</value></data>
<data name="Simulated" xml:space="preserve"><value>Simuliert</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Nicht geladen</value></data>
</root>

View File

@ -138,4 +138,7 @@
<data name="Units" xml:space="preserve">
<value />
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Cargando</value></data>
<data name="Simulated" xml:space="preserve"><value>Simulado</value></data>
<data name="Not_loaded" xml:space="preserve"><value>No cargado</value></data>
</root>

View File

@ -2028,4 +2028,7 @@
<data name="Test_time_s_chdr" xml:space="preserve">
<value>Temps test [s]</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Chargement</value></data>
<data name="Simulated" xml:space="preserve"><value>Simulé</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Non chargé</value></data>
</root>

View File

@ -1800,4 +1800,7 @@
<data name="Drain" xml:space="preserve">
<value>Drenare</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Caricamento</value></data>
<data name="Simulated" xml:space="preserve"><value>Simulato</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Non caricato</value></data>
</root>

View File

@ -1704,4 +1704,7 @@
<data name="Again" xml:space="preserve">
<value>Jeszcze raz</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Ładowanie</value></data>
<data name="Simulated" xml:space="preserve"><value>Symulacja</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Nie wczytano</value></data>
</root>

View File

@ -2494,4 +2494,13 @@
<data name="Test_in_calculation" xml:space="preserve">
<value>Test in calculation</value>
</data>
</root>
<data name="Loading" xml:space="preserve">
<value>Loading</value>
</data>
<data name="Simulated" xml:space="preserve">
<value>Simulated</value>
</data>
<data name="Not_loaded" xml:space="preserve">
<value>Not loaded</value>
</data>
</root>

View File

@ -852,4 +852,7 @@
<data name="WMSN" xml:space="preserve">
<value>seria</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Se încarcă</value></data>
<data name="Simulated" xml:space="preserve"><value>Simulat</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Neîncărcat</value></data>
</root>

View File

@ -1617,4 +1617,7 @@
<data name="Again" xml:space="preserve">
<value>Снова</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Загрузка</value></data>
<data name="Simulated" xml:space="preserve"><value>Симуляция</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Не загружено</value></data>
</root>

View File

@ -265,4 +265,7 @@
<data name="Test_in_calculation" xml:space="preserve">
<value>Prebieha výpočet</value>
</data>
</root>
<data name="Loading" xml:space="preserve"><value>Načítavanie</value></data>
<data name="Simulated" xml:space="preserve"><value>Simulácia</value></data>
<data name="Not_loaded" xml:space="preserve"><value>Nenačítané</value></data>
</root>

View File

@ -1206,4 +1206,7 @@
<data name="Units" xml:space="preserve">
<value />
</data>
</root>
<data name="Loading" xml:space="preserve"><value>正在加载</value></data>
<data name="Simulated" xml:space="preserve"><value>模拟</value></data>
<data name="Not_loaded" xml:space="preserve"><value>未加载</value></data>
</root>

View File

@ -7,6 +7,7 @@ using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common;
using log4net;
using NHibernate.Util;
using Results.Entities;
@ -443,6 +444,15 @@ namespace TBF.Rig.DataEntry.Uni
: this(waterMeters, title, myCfgBgTitle, myCfgBgSize, myCfgBgIsLrOrder, myCfgBgIsCameraPicture, myCfgBgFormCloseKeys, getItems, getColumns,AutoRead,AutoCloseGap, b)
{
this.regReaders = regReaders;
log.DebugFormat(
"DATA_ENTRY_BEGIN_FORM_CTOR AutoRead={0}, PrimarySlots={1}, PrimaryReaders={2}, " +
"SecondarySlots={3}, SecondaryReaders={4}, SameArray={5}",
bAutoRead,
regReaders == null ? 0 : regReaders.Length,
regReaders == null ? 0 : Array.FindAll(regReaders, reader => reader != null).Length,
iRegReaders == null ? 0 : iRegReaders.Length,
iRegReaders == null ? 0 : Array.FindAll(iRegReaders, reader => reader != null).Length,
ReferenceEquals(regReaders, iRegReaders));
if (bAutoRead)
{
ReadAndProcessSerialNumbersByRegReader();
@ -815,18 +825,25 @@ namespace TBF.Rig.DataEntry.Uni
log.Debug("Reading serial numbers from register readers...");
this.SerialNumberRead += (s, eArgs) =>
{
log.Debug("Serial updated: " + eArgs.SerialNumber);
log.DebugFormat(
"DATA_ENTRY_SERIAL_UI_HANDLER Name={0}, Position={1}, Serial=[{2}], Thread={3}",
eArgs.Reader == null ? "<null>" : eArgs.Reader.Name,
eArgs.Reader == null ? -1 : eArgs.Reader.Position,
eArgs.SerialNumber ?? "<null>",
System.Threading.Thread.CurrentThread.ManagedThreadId);
UpdateSomethingBySerial(eArgs.Reader, eArgs.SerialNumber);
};
BeforeUpdate();
IRegReader[] selectedRegReaders = RegisterReaderSelection.GetSelectedForDataEntry(
regReaders, log, "serial number");
BeforeUpdate(selectedRegReaders);
this.DoneUpdateBySerial += (s, eArgs) =>
{
log.Debug("Serial updated DONE!");
DoneUpdate();
};
ReadSerialNumbersAsync(regReaders);
ReadSerialNumbersAsync(selectedRegReaders);
}
private void UpdateSomethingBySerial(IRegReader eReader, string eSerialNumber)
@ -846,7 +863,7 @@ namespace TBF.Rig.DataEntry.Uni
return true; // default if nothing stored
}
private void BeforeUpdate()
private void BeforeUpdate(IEnumerable<IRegReader> selectedRegReaders)
{
log.Debug("BeforeUpdate");
@ -861,16 +878,31 @@ namespace TBF.Rig.DataEntry.Uni
_previousCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
//Enable all checkboxes
var selectedPositions = new HashSet<int>(
selectedRegReaders.Select(reader => reader.Position));
log.DebugFormat(
"DATA_ENTRY_SERIAL_UI_SELECTION SelectedCount={0}, Positions=[{1}], Watermark=[{2}]",
selectedPositions.Count, string.Join(",", selectedPositions), Strings.Loading);
// Reflect the iPerlCommunicationForm selection instead of temporarily
// checking every possible water-meter position.
for (int firstIx = 0; firstIx < wmsCount; firstIx++)
{
checkBoxes[firstIx].Checked = true;
bool selected = selectedPositions.Contains(firstIx + 1);
checkBoxes[firstIx].Checked = selected;
for (int k = 0; k < colItems.Count; k++)
{
if (colItems[k].Content != Ct.SerialNr &&
colItems[k].Content != Ct.SerialNrAux)
continue;
DataEntryWatermark.Set(
comboBoxes[k, firstIx],
selected ? Strings.Loading : string.Empty);
}
}
}
private void DoneUpdate()
{
@ -915,9 +947,15 @@ namespace TBF.Rig.DataEntry.Uni
private void PopulateComboBoxWithSerialNumbers( IRegReader eReader, string eSerialNumber)
{
if (regReaders == null || comboBoxes == null)
if (regReaders == null || comboBoxes == null || eReader == null)
{
log.WarnFormat(
"DATA_ENTRY_SERIAL_UI_SKIP ReaderNull={0}, ReadersNull={1}, ControlsNull={2}, Serial=[{3}]",
eReader == null, regReaders == null, comboBoxes == null, eSerialNumber ?? "<null>");
return;
}
bool mapped = false;
int regReadersLength = regReaders.Length;
int comboRows = comboBoxes.GetLength(0);
int comboCols = comboBoxes.GetLength(1);
@ -926,18 +964,66 @@ namespace TBF.Rig.DataEntry.Uni
{
for (int ix = 0; ix < wmsCount && ix < comboCols; ix++)
{
int regIndex = ix + wmsCount*k;
int regIndex = ix;
if (regIndex >= 0 && regIndex < regReadersLength)
{
var combo = comboBoxes[k, ix];
if (combo != null && regReaders[regIndex] == eReader)
{
mapped = true;
DataEntryWatermark.Set(combo, string.Empty);
combo.Text = eSerialNumber;
log.DebugFormat(
"DATA_ENTRY_SERIAL_UI_MAPPED Name={0}, Position={1}, Column={2}, " +
"MeterIndex={3}, Control={4}, Serial=[{5}]",
eReader.Name, eReader.Position, k, ix, combo.Name,
eSerialNumber ?? "<null>");
}
}
}
}
if (!mapped)
log.WarnFormat(
"DATA_ENTRY_SERIAL_UI_NOT_MAPPED Name={0}, Position={1}, Serial=[{2}], " +
"ReaderSlots={3}, ControlRows={4}, ControlColumns={5}",
eReader.Name, eReader.Position, eSerialNumber ?? "<null>",
regReadersLength, comboRows, comboCols);
}
private void SetSerialNumberWatermark(IRegReader reader, string watermark)
{
if (reader == null || regReaders == null || comboBoxes == null)
return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() => SetSerialNumberWatermark(reader, watermark)));
return;
}
int readerIndex = Array.IndexOf(regReaders, reader);
if (readerIndex < 0 || readerIndex >= wmsCount)
{
log.WarnFormat(
"DATA_ENTRY_SERIAL_WATERMARK_NOT_MAPPED Name={0}, Position={1}, Text=[{2}]",
reader.Name, reader.Position, watermark);
return;
}
for (int k = 0; k < colItems.Count; k++)
{
if (colItems[k].Content != Ct.SerialNr &&
colItems[k].Content != Ct.SerialNrAux)
continue;
DataEntryWatermark.Set(comboBoxes[k, readerIndex], watermark);
}
log.DebugFormat(
"DATA_ENTRY_SERIAL_WATERMARK Name={0}, Position={1}, MeterIndex={2}, Text=[{3}]",
reader.Name, reader.Position, readerIndex, watermark);
}
private void comboBox_SelectedIndexChanged(object sndr, EventArgs e)
@ -1111,12 +1197,27 @@ namespace TBF.Rig.DataEntry.Uni
protected virtual void OnSerialNumberRead(IRegReader reader, string serial)
{
log.DebugFormat(
"DATA_ENTRY_SERIAL_EVENT Name={0}, Position={1}, Serial=[{2}], Handler={3}, " +
"HandleCreated={4}, InvokeRequired={5}, Thread={6}",
reader == null ? "<null>" : reader.Name,
reader == null ? -1 : reader.Position,
serial ?? "<null>", SerialNumberRead != null,
IsHandleCreated, InvokeRequired,
System.Threading.Thread.CurrentThread.ManagedThreadId);
var handler = SerialNumberRead; // copy for thread-safety
if (handler == null) return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() =>
handler(this, new SerialNumberReadEventArgs(reader, serial))));
{
log.DebugFormat(
"DATA_ENTRY_SERIAL_EVENT_DISPATCH Name={0}, Position={1}, Thread={2}",
reader == null ? "<null>" : reader.Name,
reader == null ? -1 : reader.Position,
System.Threading.Thread.CurrentThread.ManagedThreadId);
handler(this, new SerialNumberReadEventArgs(reader, serial));
}));
}
else
{
@ -1180,8 +1281,21 @@ namespace TBF.Rig.DataEntry.Uni
// Start tasks in parallel inside subgroup
var tasks = subGroup.Select(async r =>
{
var serial = await r.DataEntry_ReadSerialNumber().ConfigureAwait(false);
return new KeyValuePair<IRegReader, string>((IRegReader)r, serial);
IRegReader reader = (IRegReader)r;
log.DebugFormat(
"DATA_ENTRY_SERIAL_READ_START Name={0}, Position={1}, DebugLevel={2}, " +
"Group={3}, SubGroup={4}, Thread={5}",
reader.Name, reader.Position, reader.DebugLevel, r.Group,
r.MuxBoardNrOrGroup14,
System.Threading.Thread.CurrentThread.ManagedThreadId);
string serial = await r.DataEntry_ReadSerialNumber().ConfigureAwait(false);
log.DebugFormat(
"DATA_ENTRY_SERIAL_READ_RESULT Name={0}, Position={1}, DebugLevel={2}, " +
"Serial=[{3}], Empty={4}, Thread={5}",
reader.Name, reader.Position, reader.DebugLevel, serial ?? "<null>",
string.IsNullOrWhiteSpace(serial),
System.Threading.Thread.CurrentThread.ManagedThreadId);
return new KeyValuePair<IRegReader, string>(reader, serial);
}).ToList();
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
@ -1191,8 +1305,20 @@ namespace TBF.Rig.DataEntry.Uni
var reader = kv.Key;
var serial = kv.Value;
if (string.IsNullOrWhiteSpace(serial))
bool simulated = reader.DebugLevel == DebugMode.Simulate;
if (simulated || string.IsNullOrWhiteSpace(serial))
{
string watermark = simulated
? Strings.Simulated
: Strings.Not_loaded;
log.WarnFormat(
"DATA_ENTRY_SERIAL_READ_IGNORED Name={0}, Position={1}, " +
"DebugLevel={2}, Reason={3}, Watermark=[{4}]",
reader.Name, reader.Position, reader.DebugLevel,
simulated ? "simulation" : "empty result", watermark);
SetSerialNumberWatermark(reader, watermark);
continue;
}
// Notify for each successful read
OnSerialNumberRead(reader, serial);

View File

@ -155,7 +155,13 @@ namespace TBF.Rig.DataEntry.Uni
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.FormAtCycleBeginning;
this.waterMeters = Sequences.ProcessData.BatchRslts.Batch.WaterMeters;
regReaders = regReadersOptional;
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;
}
@ -236,6 +242,15 @@ namespace TBF.Rig.DataEntry.Uni
}
}
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,

View File

@ -585,6 +585,8 @@ namespace TBF.Rig.DataEntry.Uni
if (bAutoRead)
{
IRegReader[] selectedRegReaders = RegisterReaderSelection.GetSelectedForDataEntry(
regReaders, log, isEnd ? "end volume" : "begin volume");
log.Debug($"Reading serial numbers from register readers... IsEnd: {isEnd}");
this.VolumeStartReadbyRegReader += (s, eArgs) =>
{
@ -592,14 +594,14 @@ namespace TBF.Rig.DataEntry.Uni
UpdateVolume(eArgs.Reader, eArgs.Volume);
};
BeforeUpdate();
BeforeUpdate(selectedRegReaders);
this.DoneUpdateByRegReader += (s, eArgs) =>
{
log.Debug("Volume updated DONE!");
DoneUpdate();
};
ReadVolumeAsync(regReaders);
ReadVolumeAsync(selectedRegReaders);
}
isHandlersEnabled = true;
@ -616,12 +618,13 @@ namespace TBF.Rig.DataEntry.Uni
return true; // default if nothing stored
}
private void BeforeUpdate()
private void BeforeUpdate(IEnumerable<IRegReader> selectedRegReaders)
{
log.Debug("BeforeUpdate");
storeUIForUpdate["okButton"] = this.okButton.Enabled;
storeUIForUpdate["largeTextBox"] = this.largeTextBox.Enabled;
storeUIForUpdate["largeTextBoxReadOnly"] = this.largeTextBox.ReadOnly;
storeUIForUpdate["largeExclamationLabel"] = this.largeExclamationLabel.Enabled;
storeUIForUpdate["unitComboBox"] = this.unitComboBox.Enabled;
@ -629,9 +632,36 @@ namespace TBF.Rig.DataEntry.Uni
this.largeTextBox.Enabled = false;
this.largeExclamationLabel.Enabled = false;
this.unitComboBox.Enabled = false;
largeTextBox.ReadOnly = true;
largeTextBox.Text = Strings.Loading;
_previousCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
var selectedPositions = new HashSet<int>(
selectedRegReaders.Select(reader => reader.Position));
log.DebugFormat(
"DATA_ENTRY_VOLUME_UI_SELECTION IsEnd={0}, SelectedCount={1}, Positions=[{2}], Watermark=[{3}]",
isEnd, selectedPositions.Count, string.Join(",", selectedPositions), Strings.Loading);
List<Ct> stateColumns = isEnd
? new List<Ct> { Ct.EndState, Ct.EndStateAux }
: new List<Ct> { Ct.StartState, Ct.StartStateAux };
for (int k = 0; k < colItems.Count; k++)
{
if (!stateColumns.Contains(colItems[k].Content))
continue;
for (int ix = 0; ix < wmsCount; ix++)
{
DataEntryWatermark.Set(
textBoxes[k, ix],
selectedPositions.Contains(ix + 1)
? Strings.Loading
: string.Empty);
}
}
}
private void DoneUpdate()
@ -641,6 +671,9 @@ namespace TBF.Rig.DataEntry.Uni
this.largeTextBox.Enabled = GetStoredOrDefault("largeTextBox");
this.largeExclamationLabel.Enabled = GetStoredOrDefault("largeExclamationLabel");
this.unitComboBox.Enabled = GetStoredOrDefault("unitComboBox");
if (largeTextBox.Text == Strings.Loading)
largeTextBox.Text = string.Empty;
largeTextBox.ReadOnly = GetStoredOrDefault("largeTextBoxReadOnly");
Cursor.Current = _previousCursor;
if (iAutocloseGap > 0)
@ -651,7 +684,10 @@ namespace TBF.Rig.DataEntry.Uni
public void UpdateVolume(IRegReader eArgsReader, double eArgsVolume)
{
log.Debug($"RegReader name: {eArgsReader.Name}, Serial No updated: " + eArgsVolume);
log.DebugFormat(
"DATA_ENTRY_VOLUME_UI_HANDLER Name={0}, Position={1}, DebugLevel={2}, Volume={3}, IsNaN={4}",
eArgsReader.Name, eArgsReader.Position, eArgsReader.DebugLevel,
eArgsVolume, Double.IsNaN(eArgsVolume));
PopulateVolume(eArgsReader, eArgsVolume);
}
@ -667,8 +703,26 @@ namespace TBF.Rig.DataEntry.Uni
public void PopulateVolume(IRegReader eArgsReader, double eArgsVolume)
{
if (regReaders == null || Double.IsNaN(eArgsVolume) || textBoxes == null)
if (eArgsReader != null && Double.IsNaN(eArgsVolume))
{
SetVolumeWatermark(
eArgsReader,
eArgsReader.DebugLevel == DebugMode.Simulate
? Strings.Simulated
: Strings.Not_loaded);
}
if (regReaders == null || Double.IsNaN(eArgsVolume) || textBoxes == null)
{
log.WarnFormat(
"DATA_ENTRY_VOLUME_UI_SKIP Name={0}, Position={1}, DebugLevel={2}, " +
"Volume={3}, ReadersNull={4}, ControlsNull={5}",
eArgsReader == null ? "<null>" : eArgsReader.Name,
eArgsReader == null ? -1 : eArgsReader.Position,
eArgsReader == null ? DebugMode.Normal : eArgsReader.DebugLevel,
eArgsVolume, regReaders == null, textBoxes == null);
return;
}
int regReadersLength = regReaders.Length;
int comboRows = textBoxes.GetLength(0);
@ -723,6 +777,7 @@ namespace TBF.Rig.DataEntry.Uni
{
try
{
DataEntryWatermark.Set(textBox, string.Empty);
if (VolumeUnit == Unit.None)
VolumeUnit = Unit.l;
Double convertTo = Units.ConvertTo(VolumeUnit, VolumeRaw);
@ -739,6 +794,36 @@ namespace TBF.Rig.DataEntry.Uni
}
}
private void SetVolumeWatermark(IRegReader reader, string watermark)
{
if (reader == null || regReaders == null || textBoxes == null)
return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() => SetVolumeWatermark(reader, watermark)));
return;
}
int readerIndex = Array.IndexOf(regReaders, reader);
if (readerIndex < 0 || readerIndex >= wmsCount)
return;
List<Ct> stateColumns = isEnd
? new List<Ct> { Ct.EndState, Ct.EndStateAux }
: new List<Ct> { Ct.StartState, Ct.StartStateAux };
for (int k = 0; k < colItems.Count; k++)
{
if (stateColumns.Contains(colItems[k].Content))
DataEntryWatermark.Set(textBoxes[k, readerIndex], watermark);
}
log.DebugFormat(
"DATA_ENTRY_VOLUME_WATERMARK Name={0}, Position={1}, MeterIndex={2}, Text=[{3}]",
reader.Name, reader.Position, readerIndex, watermark);
}
private Double findBeginStateFromForm()
{
@ -1546,6 +1631,13 @@ namespace TBF.Rig.DataEntry.Uni
// Start tasks in parallel inside subgroup
var tasks = subGroup.Select(async r =>
{
IRegReader reader = (IRegReader)r;
log.DebugFormat(
"DATA_ENTRY_VOLUME_READ_START Name={0}, Position={1}, DebugLevel={2}, " +
"Mode={3}, Group={4}, SubGroup={5}, Thread={6}",
reader.Name, reader.Position, reader.DebugLevel,
isEnd ? "end" : "begin", r.Group, r.MuxBoardNrOrGroup14,
System.Threading.Thread.CurrentThread.ManagedThreadId);
double volume = Double.NaN;
if (isEnd)
{
@ -1555,7 +1647,13 @@ namespace TBF.Rig.DataEntry.Uni
{
volume = await r.DataEntry_ReadBeginVolume().ConfigureAwait(false);
}
return new KeyValuePair<IRegReader, double>((IRegReader)r, volume);
log.DebugFormat(
"DATA_ENTRY_VOLUME_READ_RESULT Name={0}, Position={1}, DebugLevel={2}, " +
"Mode={3}, Volume={4}, IsNaN={5}, Thread={6}",
reader.Name, reader.Position, reader.DebugLevel,
isEnd ? "end" : "begin", volume, Double.IsNaN(volume),
System.Threading.Thread.CurrentThread.ManagedThreadId);
return new KeyValuePair<IRegReader, double>(reader, volume);
}).ToList();
var results = await Task.WhenAll(tasks).ConfigureAwait(false);

View File

@ -535,6 +535,38 @@ namespace TBF.Rig.Sequences
ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithPurgingTests[0]).RegisterReaders;
}
// Some procedures do not have a communication test simultaneous with purging.
// Resolve their first usable meter path before opening the cycle-begin dialog.
if (ProcessData.RegisterReaders == null ||
!ProcessData.RegisterReaders.Any(reader => reader != null))
{
foreach (Test procedureTest in StateMachine.Procedure.Tests)
{
MetersPath metersPath = StateMachine.GetMetersPath(procedureTest);
if (metersPath == null || metersPath.RegisterReaders == null ||
!metersPath.RegisterReaders.Any(reader => reader != null))
continue;
ProcessData.RegisterReaders = metersPath.RegisterReaders;
log.DebugFormat(
"DATA_ENTRY_BEGIN_READERS_RESOLVED Test={0}, Slots={1}, Readers={2}, Positions=[{3}]",
procedureTest.Name,
ProcessData.RegisterReaders.Length,
ProcessData.RegisterReaders.Count(reader => reader != null),
string.Join(",", ProcessData.RegisterReaders
.Where(reader => reader != null)
.Select(reader => reader.Position)));
break;
}
if (ProcessData.RegisterReaders == null ||
!ProcessData.RegisterReaders.Any(reader => reader != null))
{
log.Warn(
"DATA_ENTRY_BEGIN_READERS_NOT_RESOLVED No procedure test contains an active register reader");
}
}
if (!OpenCycleBeginForm(ProcessData.RegisterReaders))
{
goto stop;

View File

@ -1571,9 +1571,9 @@ namespace TBF.Rig.Sequences
tstRslt.TestTime = tstRslt.TargetTime();
tstRslt.PulsesMaster = (flowMeterLtrPerPulse > 1E-6) ? (1.0075 * tstRslt.TargetVolume() / flowMeterLtrPerPulse) : 1;
tstRslt.MassStartRaw = 0;
tstRslt.MassStart = MeasurementCorrection.CorrectedValue(tstRslt.MassStartRaw, outPath.Scale.Corrections);
tstRslt.MassStart = MeasurementCorrection.CorrectedValue(tstRslt.MassStartRaw, outPath.Scale?.Corrections);
tstRslt.MassEndRaw = tstRslt.TargetVolume() * Formulas.RealDensity() / 1000.0f;
tstRslt.MassEnd = MeasurementCorrection.CorrectedValue(tstRslt.MassEndRaw, outPath.Scale.Corrections);
tstRslt.MassEnd = MeasurementCorrection.CorrectedValue(tstRslt.MassEndRaw, outPath.Scale?.Corrections);
tstRslt.Flow = 3.6 * flowMeterLtrPerPulse * tstRslt.PulsesMaster / tstRslt.TestTime;
tstRslt.MassOfEvapWater = 0;
tstRslt.VolumeCTV = 1000 * tstRslt.Batch.Buoyancy * (tstRslt.MassEnd - tstRslt.MassStart) / tstRslt.DensityLine; /// [l] commercially true volume

View File

@ -641,6 +641,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
}
long checkboxStates = GetCheckBoxStates();
log.WarnFormat(
"IPERL_SELECTION_CLOSE Previous=0x{0:X12}, Current=0x{1:X12}, " +
"DisplayedPositions=[{2}], SelectedDisplayedPositions=[{3}]",
Program.LocalSettings.OptoHeadsEnabled, checkboxStates,
string.Join(",", displayedHeadPositions0.Select(position => position + 1)),
string.Join(",", displayedHeadPositions0
.Where(position => (checkboxStates & (1L << position)) != 0)
.Select(position => position + 1)));
if (Program.LocalSettings.iPerlCommunicationsFormLeft != Location.X ||
Program.LocalSettings.iPerlCommunicationsFormTop != Location.Y ||
Program.LocalSettings.OptoHeadsEnabled != checkboxStates)
@ -3116,7 +3124,18 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
private void saveButton_Click(object sender, EventArgs e)
{
Program.LocalSettings.OptoHeadsEnabled = GetCheckBoxStates();
long previousStates = Program.LocalSettings.OptoHeadsEnabled;
long checkboxStates = GetCheckBoxStates();
log.WarnFormat(
"IPERL_SELECTION_SAVE Previous=0x{0:X12}, Current=0x{1:X12}, " +
"DisplayedPositions=[{2}], SelectedDisplayedPositions=[{3}]",
previousStates, checkboxStates,
string.Join(",", displayedHeadPositions0.Select(position => position + 1)),
string.Join(",", displayedHeadPositions0
.Where(position => (checkboxStates & (1L << position)) != 0)
.Select(position => position + 1)));
Program.LocalSettings.OptoHeadsEnabled = checkboxStates;
Program.LocalSettings.Save();
DialogResult = DialogResult.OK;
Close();

View File

@ -752,12 +752,14 @@
<Compile Include="Rig\DataEntry\Uni\CycleBgEnForm.designer.cs">
<DependentUpon>CycleBgEnForm.cs</DependentUpon>
</Compile>
<Compile Include="Rig\DataEntry\Uni\DataEntryWatermark.cs" />
<Compile Include="Rig\DataEntry\Uni\EntryForm.cs" />
<Compile Include="Rig\DataEntry\Uni\EntryFormCfg.cs" />
<Compile Include="Rig\DataEntry\Uni\EntryFormNoStartEnd.cs" />
<Compile Include="Rig\DataEntry\Uni\Factory.cs" />
<Compile Include="Rig\DataEntry\Uni\FactoryNoStartEnd.cs" />
<Compile Include="Rig\DataEntry\Uni\ProcParams.cs" />
<Compile Include="Rig\DataEntry\Uni\RegisterReaderSelection.cs" />
<Compile Include="Rig\DataEntry\Uni\TestStartEndForm.cs">
<SubType>Form</SubType>
</Compile>