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