diff --git a/TBF/Resources/Strings.Designer.cs b/TBF/Resources/Strings.Designer.cs
index 36d84ecf8..dec447462 100644
--- a/TBF/Resources/Strings.Designer.cs
+++ b/TBF/Resources/Strings.Designer.cs
@@ -7190,5 +7190,32 @@ namespace TBF.Resources {
return ResourceManager.GetString("Zeroing_chdr", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Loading.
+ ///
+ internal static string Loading {
+ get {
+ return ResourceManager.GetString("Loading", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Simulated.
+ ///
+ internal static string Simulated {
+ get {
+ return ResourceManager.GetString("Simulated", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Not loaded.
+ ///
+ internal static string Not_loaded {
+ get {
+ return ResourceManager.GetString("Not_loaded", resourceCulture);
+ }
+ }
}
}
diff --git a/TBF/Resources/Strings.cs.resx b/TBF/Resources/Strings.cs.resx
index 00234e6e2..384fd755d 100644
--- a/TBF/Resources/Strings.cs.resx
+++ b/TBF/Resources/Strings.cs.resx
@@ -1767,4 +1767,7 @@
Znovu otevřít
-
\ No newline at end of file
+ Načítání
+ Simulace
+ Nenačteno
+
diff --git a/TBF/Resources/Strings.de.resx b/TBF/Resources/Strings.de.resx
index 2ce6b09c4..4036991fb 100644
--- a/TBF/Resources/Strings.de.resx
+++ b/TBF/Resources/Strings.de.resx
@@ -2229,4 +2229,7 @@
Abtastkopf wurde deaktiviert vom Benutzer!
-
\ No newline at end of file
+ Laden
+ Simuliert
+ Nicht geladen
+
diff --git a/TBF/Resources/Strings.es.resx b/TBF/Resources/Strings.es.resx
index 2e116070f..550138cfa 100644
--- a/TBF/Resources/Strings.es.resx
+++ b/TBF/Resources/Strings.es.resx
@@ -138,4 +138,7 @@
-
\ No newline at end of file
+ Cargando
+ Simulado
+ No cargado
+
diff --git a/TBF/Resources/Strings.fr.resx b/TBF/Resources/Strings.fr.resx
index f37f2e22d..f02bb973b 100644
--- a/TBF/Resources/Strings.fr.resx
+++ b/TBF/Resources/Strings.fr.resx
@@ -2028,4 +2028,7 @@
Temps test [s]
-
\ No newline at end of file
+ Chargement
+ Simulé
+ Non chargé
+
diff --git a/TBF/Resources/Strings.it.resx b/TBF/Resources/Strings.it.resx
index c1b24abd9..63af18898 100644
--- a/TBF/Resources/Strings.it.resx
+++ b/TBF/Resources/Strings.it.resx
@@ -1800,4 +1800,7 @@
Drenare
-
\ No newline at end of file
+ Caricamento
+ Simulato
+ Non caricato
+
diff --git a/TBF/Resources/Strings.pl.resx b/TBF/Resources/Strings.pl.resx
index 50978605f..6bc23debc 100644
--- a/TBF/Resources/Strings.pl.resx
+++ b/TBF/Resources/Strings.pl.resx
@@ -1704,4 +1704,7 @@
Jeszcze raz
-
\ No newline at end of file
+ Ładowanie
+ Symulacja
+ Nie wczytano
+
diff --git a/TBF/Resources/Strings.resx b/TBF/Resources/Strings.resx
index fb5f56b04..fffff6ce9 100644
--- a/TBF/Resources/Strings.resx
+++ b/TBF/Resources/Strings.resx
@@ -2494,4 +2494,13 @@
Test in calculation
-
\ No newline at end of file
+
+ Loading
+
+
+ Simulated
+
+
+ Not loaded
+
+
diff --git a/TBF/Resources/Strings.ro.resx b/TBF/Resources/Strings.ro.resx
index 1f9f1fbba..d8e9c562d 100644
--- a/TBF/Resources/Strings.ro.resx
+++ b/TBF/Resources/Strings.ro.resx
@@ -852,4 +852,7 @@
seria
-
\ No newline at end of file
+ Se încarcă
+ Simulat
+ Neîncărcat
+
diff --git a/TBF/Resources/Strings.ru.resx b/TBF/Resources/Strings.ru.resx
index eeb2d30f8..f113dfafd 100644
--- a/TBF/Resources/Strings.ru.resx
+++ b/TBF/Resources/Strings.ru.resx
@@ -1617,4 +1617,7 @@
Снова
-
\ No newline at end of file
+ Загрузка
+ Симуляция
+ Не загружено
+
diff --git a/TBF/Resources/Strings.sk.resx b/TBF/Resources/Strings.sk.resx
index 0f17f5f1e..e298a08d7 100644
--- a/TBF/Resources/Strings.sk.resx
+++ b/TBF/Resources/Strings.sk.resx
@@ -265,4 +265,7 @@
Prebieha výpočet
-
\ No newline at end of file
+ Načítavanie
+ Simulácia
+ Nenačítané
+
diff --git a/TBF/Resources/Strings.zh-CN.resx b/TBF/Resources/Strings.zh-CN.resx
index ff3de7a90..96903027d 100644
--- a/TBF/Resources/Strings.zh-CN.resx
+++ b/TBF/Resources/Strings.zh-CN.resx
@@ -1206,4 +1206,7 @@
-
\ No newline at end of file
+ 正在加载
+ 模拟
+ 未加载
+
diff --git a/TBF/Rig/DataEntry/Uni/CycleBgEnForm.cs b/TBF/Rig/DataEntry/Uni/CycleBgEnForm.cs
index e84674d4e..e665a728b 100644
--- a/TBF/Rig/DataEntry/Uni/CycleBgEnForm.cs
+++ b/TBF/Rig/DataEntry/Uni/CycleBgEnForm.cs
@@ -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 ? "" : eArgs.Reader.Name,
+ eArgs.Reader == null ? -1 : eArgs.Reader.Position,
+ eArgs.SerialNumber ?? "",
+ 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 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(
+ 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 ?? "");
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 ?? "");
}
}
}
}
+
+ 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 ?? "",
+ 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 ? "" : reader.Name,
+ reader == null ? -1 : reader.Position,
+ serial ?? "", 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 ? "" : 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)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 ?? "",
+ string.IsNullOrWhiteSpace(serial),
+ System.Threading.Thread.CurrentThread.ManagedThreadId);
+ return new KeyValuePair(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);
diff --git a/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs b/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs
index 5482a1b55..829d74822 100644
--- a/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs
+++ b/TBF/Rig/DataEntry/Uni/EntryFormNoStartEnd.cs
@@ -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,
diff --git a/TBF/Rig/DataEntry/Uni/TestStartEndForm.cs b/TBF/Rig/DataEntry/Uni/TestStartEndForm.cs
index 0b656c3e3..bde2fc778 100644
--- a/TBF/Rig/DataEntry/Uni/TestStartEndForm.cs
+++ b/TBF/Rig/DataEntry/Uni/TestStartEndForm.cs
@@ -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 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(
+ 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 stateColumns = isEnd
+ ? new List { Ct.EndState, Ct.EndStateAux }
+ : new List { 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 ? "" : 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 stateColumns = isEnd
+ ? new List { Ct.EndState, Ct.EndStateAux }
+ : new List { 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)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(reader, volume);
}).ToList();
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
diff --git a/TBF/Rig/Sequences/MainSeq.cs b/TBF/Rig/Sequences/MainSeq.cs
index ae6a22162..cc20b161b 100644
--- a/TBF/Rig/Sequences/MainSeq.cs
+++ b/TBF/Rig/Sequences/MainSeq.cs
@@ -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;
diff --git a/TBF/Rig/Sequences/SequenceBase.cs b/TBF/Rig/Sequences/SequenceBase.cs
index 546de42d7..d3010bb8c 100644
--- a/TBF/Rig/Sequences/SequenceBase.cs
+++ b/TBF/Rig/Sequences/SequenceBase.cs
@@ -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
diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs
index 94dc7e846..6d35b592c 100644
--- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs
+++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs
@@ -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();
diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj
index 523220d10..4a1bfa056 100644
--- a/TBF/TBF.csproj
+++ b/TBF/TBF.csproj
@@ -752,12 +752,14 @@
CycleBgEnForm.cs
+
+
Form